forked from nique_372/CryptoByLeo
479 lines
15 KiB
MQL5
479 lines
15 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| TestNistVectors.mqh |
|
|
//| Copyright 2026, Niquel Mendoza |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2026, Niquel Mendoza"
|
|
#property link "https://www.mql5.com"
|
|
#property strict
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
#include <TSN\\MqlCI\\UnitTest.mqh>
|
|
#include <TSN\\Json\\Json.mqh>
|
|
#include "..\\Src\\RSPParser\\Iteradores.mqh"
|
|
#include "..\\Src\\Hash\\All.mqh"
|
|
#include "..\\Src\\Simetric\\AES\\Main.mqh"
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
namespace TSN
|
|
{
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
// todos los archivos en folder RSPTestVectores en common
|
|
const string g_rsptestvector_sha3_512_fn[2] =
|
|
{
|
|
"RSPTestVectores\\SHA3\\SHA3_512LongMsg.rsp",
|
|
"RSPTestVectores\\SHA3\\SHA3_512ShortMsg.rsp",
|
|
};
|
|
const string g_rsptestvector_sha3_384_fn[2] =
|
|
{
|
|
"RSPTestVectores\\SHA3\\SHA3_384LongMsg.rsp",
|
|
"RSPTestVectores\\SHA3\\SHA3_384ShortMsg.rsp",
|
|
};
|
|
const string g_rsptestvector_sha3_256_fn[2] =
|
|
{
|
|
"RSPTestVectores\\SHA3\\SHA3_256LongMsg.rsp",
|
|
"RSPTestVectores\\SHA3\\SHA3_256ShortMsg.rsp",
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
const string g_rsptestvector_sha2_256_fn[2] =
|
|
{
|
|
"RSPTestVectores\\SHA2\\SHA256LongMsg.rsp",
|
|
"RSPTestVectores\\SHA2\\SHA256ShortMsg.rsp",
|
|
};
|
|
const string g_rsptestvector_sha2_384_fn[2] =
|
|
{
|
|
"RSPTestVectores\\SHA2\\SHA384LongMsg.rsp",
|
|
"RSPTestVectores\\SHA2\\SHA384ShortMsg.rsp",
|
|
};
|
|
const string g_rsptestvector_sha2_512_224_fn[2] =
|
|
{
|
|
"RSPTestVectores\\SHA2\\SHA512_224LongMsg.rsp",
|
|
"RSPTestVectores\\SHA2\\SHA512_224ShortMsg.rsp",
|
|
};
|
|
const string g_rsptestvector_sha2_512_256_fn[2] =
|
|
{
|
|
"RSPTestVectores\\SHA2\\SHA512_256LongMsg.rsp",
|
|
"RSPTestVectores\\SHA2\\SHA512_256ShortMsg.rsp",
|
|
};
|
|
const string g_rsptestvector_sha2_512_fn[2] =
|
|
{
|
|
"RSPTestVectores\\SHA2\\SHA512LongMsg.rsp",
|
|
"RSPTestVectores\\SHA2\\SHA512ShortMsg.rsp",
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
#define BLAKE2_JSONFILE ("RSPTestVectores\\BLAKE2\\blake2b_kat_vectors.json")
|
|
|
|
//+------------------------------------------------------------------+
|
|
const string g_rsptestvector_aes_cbc_256[4] =
|
|
{
|
|
"RSPTestVectores\\AES\\256\\CBCGFSbox256.rsp",
|
|
"RSPTestVectores\\AES\\256\\CBCKeySbox256.rsp",
|
|
"RSPTestVectores\\AES\\256\\CBCVarKey256.rsp",
|
|
"RSPTestVectores\\AES\\256\\CBCVarTxt256.rsp"
|
|
};
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
const string g_rsptestvector_aes_cbc_128[4] =
|
|
{
|
|
"RSPTestVectores\\AES\\128\\CBCGFSbox128.rsp",
|
|
"RSPTestVectores\\AES\\128\\CBCKeySbox128.rsp",
|
|
"RSPTestVectores\\AES\\128\\CBCVarKey128.rsp",
|
|
"RSPTestVectores\\AES\\128\\CBCVarTxt128.rsp"
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
const string g_rsptestvector_aes_ecb_256[4] =
|
|
{
|
|
"RSPTestVectores\\AES\\256\\ECBGFSbox256.rsp",
|
|
"RSPTestVectores\\AES\\256\\ECBKeySbox256.rsp",
|
|
"RSPTestVectores\\AES\\256\\ECBVarKey256.rsp",
|
|
"RSPTestVectores\\AES\\256\\ECBVarTxt256.rsp"
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
const string g_rsptestvector_aes_ecb_128[4] =
|
|
{
|
|
"RSPTestVectores\\AES\\128\\ECBGFSbox128.rsp",
|
|
"RSPTestVectores\\AES\\128\\ECBKeySbox128.rsp",
|
|
"RSPTestVectores\\AES\\128\\ECBVarKey128.rsp",
|
|
"RSPTestVectores\\AES\\128\\ECBVarTxt128.rsp"
|
|
};
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename THashSize>
|
|
class CTestNistVectors_SHA : public ICiTest
|
|
{
|
|
private:
|
|
string m_name;
|
|
string m_arry_fn_test[2]; // 1=short, 2=long
|
|
CCryptoHashMeta::TsnCryptoByLeoHashFuncFixed m_func;
|
|
|
|
public:
|
|
CTestNistVectors_SHA(const string& name, const string& arr[], CCryptoHashMeta::TsnCryptoByLeoHashFuncFixed f)
|
|
: m_name(name), m_func(f)
|
|
{ ArrayCopy(m_arry_fn_test, arr, 0, 0, 2); }
|
|
~CTestNistVectors_SHA(void) {}
|
|
|
|
//---
|
|
inline string Name() const override final { return m_name; }
|
|
inline int Importance() const override final { return 100; }
|
|
bool Run(string &msg) override final;
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename THashSize>
|
|
bool CTestNistVectors_SHA::Run(string &msg)
|
|
{
|
|
//---
|
|
CRSPParser rsp;
|
|
|
|
//---
|
|
uchar bytes[];
|
|
uchar out[sizeof(THashSize)];
|
|
uchar md[];
|
|
|
|
//---
|
|
for(int z = 0; z < 2; z++)
|
|
{
|
|
const int ext = rsp.AssingFile(m_arry_fn_test[z], true);
|
|
if(rsp.AutoParseByFileExt(ext))
|
|
{
|
|
msg = StringFormat("Fallo al parser .rsp, last err = %s", EnumToString(rsp.LastErr()));
|
|
return false;
|
|
}
|
|
|
|
//---
|
|
CRSPNode node = rsp.GetRoot();
|
|
|
|
//--- movemos
|
|
node.MoveNextPositionsThis(3); // justo en siguiente posicio
|
|
|
|
//--- armamos el iterador
|
|
const string keys[3] = {"Len", "Msg", "MD"};
|
|
CRSPIteratorHashFast(3) it = node.MakeHashIterator<RSPNODE_NH(3), TSN::CGenericHash_string>(keys);
|
|
|
|
//---
|
|
while(it.IsValid())
|
|
{
|
|
//const int len = int(it["Len"].Value().ToString()) >> 2; // /8
|
|
|
|
//--- MD (Expected)
|
|
it["MD"].Value().HexToBytes(md);
|
|
|
|
//--- convetimos a bytes el mensaje
|
|
it["Msg"].Value().HexToBytes(bytes);
|
|
|
|
//---
|
|
m_func(bytes, 0, out, 0);
|
|
|
|
//--- comparemos
|
|
if(!CRSPNode::BytesEq(md, out))
|
|
{
|
|
msg = StringFormat("Hash no coindice Counter=%d en msg:\n[%s]\nFile:\n%s", it.ReadPars(),
|
|
it["Msg"].Value().ToString(),
|
|
m_arry_fn_test[z]);
|
|
return false;
|
|
}
|
|
|
|
//---
|
|
it.Next();
|
|
}
|
|
}
|
|
//---
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
class CTest_BLAKE2 : public ICiTest
|
|
{
|
|
public:
|
|
CTest_BLAKE2(void) {}
|
|
~CTest_BLAKE2(void) {}
|
|
|
|
|
|
inline string Name() const override final { return "BLAKE2 Official vector test"; }
|
|
inline int Importance() const override final { return 100; }
|
|
bool Run(string &msg) override final;
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
bool CTest_BLAKE2::Run(string &msg)
|
|
{
|
|
CJsonParser json;
|
|
const int ext = json.AssingFile(BLAKE2_JSONFILE, true);
|
|
if(!json.AutoParseByFileExt(ext))
|
|
{
|
|
msg = StringFormat("Error in parsing json last err = %s", EnumToString(json.LastErr()));
|
|
return false;
|
|
}
|
|
|
|
//---
|
|
CJsonIteratorArray it = json.GetRoot().BeginArr();
|
|
uchar in[];
|
|
uchar out[64];
|
|
uchar expected[];
|
|
const int locked = it.m_cur;
|
|
|
|
//---
|
|
while(it.IsValid())
|
|
{
|
|
CJsonNode value = it.Val();
|
|
const int tin = value["input"].HexToBytes(in);
|
|
const int tout = value["out"].HexToBytes(expected);
|
|
CCryptoHash::BLAKE2B(in, tin, out, tout);
|
|
|
|
//--- comparemos
|
|
if(!CRSPNode::BytesEq(out, expected))
|
|
{
|
|
msg = StringFormat("Hash no coindice Counter=%d en msg:\n[%s]", (it.m_cur - locked) / 8,
|
|
value["input"].ToString());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//---
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
class CTest_AES_ECB : public ICiTest
|
|
{
|
|
private:
|
|
string m_name;
|
|
string m_arr_fn[4];
|
|
CAes m_aes;
|
|
|
|
public:
|
|
CTest_AES_ECB(const string& inarr[], const string& name, ENUM_AES_TYPE_CRYPTH m);
|
|
~CTest_AES_ECB(void) {}
|
|
|
|
|
|
//---
|
|
inline string Name() const override final { return m_name; }
|
|
inline int Importance() const override final { return 100; }
|
|
bool Run(string &msg) override final;
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
CTest_AES_ECB::CTest_AES_ECB(const string& inarr[], const string& name, ENUM_AES_TYPE_CRYPTH m)
|
|
: m_name(name)
|
|
{
|
|
ArrayCopy(m_arr_fn, inarr, 0, 0, 4);
|
|
m_aes.Method(m);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool CTest_AES_ECB::Run(string &msg)
|
|
{
|
|
//---
|
|
CRSPParser rsp;
|
|
|
|
//--- armamos el iterador (masra de iteraciones)
|
|
const string keys[4] = {"COUNT", "KEY", "PLAINTEXT", "CIPHERTEXT"};
|
|
CRSPIteratorHashFast(4) it = CRSPIteratorHashFast(4)(keys, &rsp, 0);
|
|
|
|
//---
|
|
uchar bytes[];
|
|
uchar out[];
|
|
uchar chiper[];
|
|
uchar key[];
|
|
|
|
//---
|
|
for(int z = 0; z < 4; z++)
|
|
{
|
|
const int ext = rsp.AssingFile(m_arr_fn[z], true);
|
|
if(rsp.AutoParseByFileExt(ext))
|
|
{
|
|
msg = StringFormat("Fallo al parser .rsp, last err = %s", EnumToString(rsp.LastErr()));
|
|
return false;
|
|
}
|
|
|
|
//--- movemos
|
|
it.RecalcLen(); // recaluclso del len (para el contexto)
|
|
it = 3; // posicion 3
|
|
|
|
//--- Encrypt
|
|
while(it.IsValid())
|
|
{
|
|
it["CIPHERTEXT"].Value().HexToBytes(chiper);
|
|
it["PLAINTEXT"].Value().HexToBytes(bytes);
|
|
it["KEY"].Value().HexToBytes(key);
|
|
m_aes.Init(key);
|
|
m_aes.Cifrar(bytes);
|
|
if(!CRSPNode::BytesEq(bytes, chiper))
|
|
{
|
|
msg = StringFormat("Hash no coindice Counter=%d en msg:\n[%s]\nFile:\n%s", it.ReadPars(),
|
|
it["PLAINTEXT"].Value().ToString(),
|
|
m_arr_fn[z]);
|
|
return false;
|
|
}
|
|
it.Next();
|
|
}
|
|
|
|
//---
|
|
it.ResetLast();
|
|
// ahora mismo en meta
|
|
it.Next(); // avanzamos otra posicion
|
|
// ahora si nos ubicamos en valores... empezemos
|
|
|
|
//--- decrypt
|
|
while(it.IsValid())
|
|
{
|
|
it["CIPHERTEXT"].Value().HexToBytes(chiper);
|
|
it["PLAINTEXT"].Value().HexToBytes(bytes);
|
|
it["KEY"].Value().HexToBytes(key);
|
|
m_aes.Init(key);
|
|
m_aes.CifradoInverso(chiper); // ahora chiper esta descifrado comparmos con plaintext
|
|
if(!CRSPNode::BytesEq(bytes, chiper))
|
|
{
|
|
msg = StringFormat("Hash no coindice Counter=%d en msg:\n[%s]\nFile:\n%s", it.ReadPars(),
|
|
it["CIPHERTEXT"].Value().ToString(),
|
|
m_arr_fn[z]);
|
|
return false;
|
|
}
|
|
it.Next();
|
|
}
|
|
}
|
|
//---
|
|
return true;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
class CTest_AES_CBC : public ICiTest
|
|
{
|
|
private:
|
|
string m_name;
|
|
string m_arr_fn[4];
|
|
CAes m_aes;
|
|
|
|
public:
|
|
CTest_AES_CBC(const string& inarr[], const string& name, ENUM_AES_TYPE_CRYPTH m);
|
|
~CTest_AES_CBC(void) {}
|
|
|
|
|
|
//---
|
|
inline string Name() const override final { return m_name; }
|
|
inline int Importance() const override final { return 100; }
|
|
bool Run(string &msg) override final;
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
CTest_AES_CBC::CTest_AES_CBC(const string& inarr[], const string& name, ENUM_AES_TYPE_CRYPTH m)
|
|
: m_name(name)
|
|
{
|
|
ArrayCopy(m_arr_fn, inarr, 0, 0, 4);
|
|
m_aes.Method(m);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool CTest_AES_CBC::Run(string &msg)
|
|
{
|
|
//---
|
|
CRSPParser rsp;
|
|
|
|
//--- armamos el iterador (masra de iteraciones)
|
|
const string keys[5] = {"COUNT", "KEY", "IV", "PLAINTEXT", "CIPHERTEXT"};
|
|
CRSPIteratorHashFast(5) it = CRSPIteratorHashFast(5)(keys, &rsp, 0);
|
|
|
|
//---
|
|
uchar bytes[];
|
|
uchar out[];
|
|
uchar chiper[];
|
|
uchar key[];
|
|
uchar iv[];
|
|
|
|
//---
|
|
for(int z = 0; z < 4; z++)
|
|
{
|
|
const int ext = rsp.AssingFile(m_arr_fn[z], true);
|
|
if(rsp.AutoParseByFileExt(ext))
|
|
{
|
|
msg = StringFormat("Fallo al parser .rsp, last err = %s", EnumToString(rsp.LastErr()));
|
|
return false;
|
|
}
|
|
|
|
//--- movemos
|
|
it.RecalcLen(); // recaluclso del len (para el contexto)
|
|
it = 3; // posicion 3
|
|
|
|
//--- Encrypt
|
|
while(it.IsValid())
|
|
{
|
|
it["CIPHERTEXT"].Value().HexToBytes(chiper); // valor esperado
|
|
const int t = it["PLAINTEXT"].Value().HexToBytes(bytes); // lo que nos dan
|
|
it["KEY"].Value().HexToBytes(key);
|
|
it["IV"].Value().HexToBytes(iv);
|
|
m_aes.Init(key, iv);
|
|
m_aes.CbcCifrado(bytes, t);
|
|
if(!CRSPNode::BytesEq(bytes, chiper))
|
|
{
|
|
msg = StringFormat("Encryptado no coindice Counter=%d en msg:\n[%s]\nFile:\n%s", it.ReadPars(),
|
|
it["CIPHERTEXT"].Value().ToString(),
|
|
m_arr_fn[z]);
|
|
return false;
|
|
}
|
|
it.Next();
|
|
}
|
|
|
|
//---
|
|
it.ResetLast();
|
|
// ahora mismo en meta
|
|
it.Next(); // avanzamos otra posicion
|
|
// ahora si nos ubicamos en valores... empezemos
|
|
|
|
//--- decrypt
|
|
while(it.IsValid())
|
|
{
|
|
const int t = it["CIPHERTEXT"].Value().HexToBytes(chiper); // lo que nos dan
|
|
it["PLAINTEXT"].Value().HexToBytes(bytes); // valor esperado
|
|
it["KEY"].Value().HexToBytes(key);
|
|
it["IV"].Value().HexToBytes(iv);
|
|
m_aes.Init(key, iv);
|
|
m_aes.CbcDescifra(chiper, t); // ahora descihfrunso chiper (no es necesario padding ni nada aqui)
|
|
if(!CRSPNode::BytesEq(bytes, chiper))
|
|
{
|
|
msg = StringFormat("Desencryptado no coindice Counter=%d en msg:\n[%s]\nFile:\n%s", it.ReadPars(),
|
|
it["PLAINTEXT"].Value().ToString(),
|
|
m_arr_fn[z]);
|
|
return false;
|
|
}
|
|
it.Next();
|
|
}
|
|
}
|
|
//---
|
|
return true;
|
|
}
|
|
|
|
//---
|
|
}
|
|
//+------------------------------------------------------------------+
|