CryptoByLeo/Wf/TestNistVectors.mqh
Nique_372 b2b951141a
2026-08-26 10:58:53 -05:00

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;
}
//---
}
//+------------------------------------------------------------------+