CryptoByLeo/Wf/TestNistVectors.mqh

504 lines
16 KiB
MQL5

2026-08-25 09:19:11 -05:00
//+------------------------------------------------------------------+
//| 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>
2026-08-25 09:19:11 -05:00
#include "..\\Src\\RSPParser\\Iteradores.mqh"
#include "..\\Src\\Hash\\All.mqh"
#include "..\\Src\\Simetric\\AES\\Main.mqh"
2026-08-25 09:19:11 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
namespace TSN
{
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-08-25 20:10:08 -05:00
// 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",
2026-08-25 20:10:08 -05:00
};
const string g_rsptestvector_sha3_384_fn[2] =
{
"RSPTestVectores\\SHA3\\SHA3_384LongMsg.rsp",
"RSPTestVectores\\SHA3\\SHA3_384ShortMsg.rsp",
2026-08-25 20:10:08 -05:00
};
const string g_rsptestvector_sha3_256_fn[2] =
{
"RSPTestVectores\\SHA3\\SHA3_256LongMsg.rsp",
"RSPTestVectores\\SHA3\\SHA3_256ShortMsg.rsp",
2026-08-25 20:10:08 -05:00
};
//+------------------------------------------------------------------+
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")
//+------------------------------------------------------------------+
2026-08-26 10:58:53 -05:00
const string g_rsptestvector_aes_cbc_256[4] =
{
2026-08-26 10:58:53 -05:00
"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] =
{
2026-08-26 10:58:53 -05:00
"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"
};
2026-08-25 20:10:08 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename THashSize>
class CTestNistVectors_SHA : public ICiTest
2026-08-25 09:19:11 -05:00
{
2026-08-25 20:10:08 -05:00
private:
string m_name;
string m_arry_fn_test[2]; // 1=short, 2=long
CCryptoHashMeta::TsnCryptoByLeoHashFuncFixed m_func;
2026-08-25 09:19:11 -05:00
public:
CTestNistVectors_SHA(const string& name, const string& arr[], CCryptoHashMeta::TsnCryptoByLeoHashFuncFixed f)
2026-08-25 20:10:08 -05:00
: m_name(name), m_func(f)
{ ArrayCopy(m_arry_fn_test, arr, 0, 0, 2); }
~CTestNistVectors_SHA(void) {}
2026-08-25 09:19:11 -05:00
//---
2026-08-25 20:10:08 -05:00
inline string Name() const override final { return m_name; }
2026-08-25 09:19:11 -05:00
inline int Importance() const override final { return 100; }
bool Run(string &msg) override final;
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-08-25 20:10:08 -05:00
template <typename THashSize>
bool CTestNistVectors_SHA::Run(string &msg)
2026-08-25 09:19:11 -05:00
{
2026-08-25 20:10:08 -05:00
//---
2026-08-25 09:19:11 -05:00
CRSPParser rsp;
2026-08-26 09:31:56 -05:00
//---
uchar bytes[];
uchar out[sizeof(THashSize)];
uchar md[];
2026-09-02 07:22:44 -05:00
//---
const string keys[3] = {"Len", "Msg", "MD"};
CRSPIteratorHashFast(3) it = CRSPIteratorHashFast(3)(keys, &rsp, 0);
2026-08-25 09:19:11 -05:00
//---
2026-08-25 20:10:08 -05:00
for(int z = 0; z < 2; z++)
{
const int ext = rsp.AssingFile(m_arry_fn_test[z], true);
2026-09-02 07:22:44 -05:00
if(!rsp.AutoParseByFileExt(ext))
2026-08-25 20:10:08 -05:00
{
msg = StringFormat("Fallo al parser .rsp, last err = %s", EnumToString(rsp.LastErr()));
return false;
}
2026-08-25 09:19:11 -05:00
2026-08-25 20:10:08 -05:00
//--- armamos el iterador
2026-09-02 07:22:44 -05:00
it.RecalcLen();
2026-09-02 08:18:46 -05:00
it = 1;
2026-08-25 09:19:11 -05:00
2026-08-25 20:10:08 -05:00
//---
while(it.IsValid())
{
//const int len = int(it["Len"].Value().ToString()) >> 2; // /8
2026-08-25 09:19:11 -05:00
2026-08-25 20:10:08 -05:00
//--- MD (Expected)
it["MD"].Value().HexToBytes(md);
2026-08-25 09:19:11 -05:00
2026-08-25 20:10:08 -05:00
//--- convetimos a bytes el mensaje
2026-09-02 07:22:44 -05:00
int t = it["Msg"].Value().HexToBytes(bytes);
if(int(it["Len"].Value().ToString()) == 0)
t = 0; // puede retornar 1
2026-08-25 09:19:11 -05:00
2026-08-25 20:10:08 -05:00
//---
2026-09-02 07:22:44 -05:00
m_func(bytes, t, out, 0);
2026-08-25 09:19:11 -05:00
2026-08-25 20:10:08 -05:00
//--- 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]);
2026-08-25 20:10:08 -05:00
return false;
}
2026-08-25 09:19:11 -05:00
2026-08-25 20:10:08 -05:00
//---
it.Next();
}
}
2026-08-25 09:19:11 -05:00
//---
return true;
}
2026-08-25 20:10:08 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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;
2026-08-25 20:10:08 -05:00
//---
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;
}
2026-09-02 07:22:44 -05:00
it.Next();
}
2026-08-25 20:10:08 -05:00
//---
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);
2026-08-26 09:31:56 -05:00
//---
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);
2026-09-02 07:22:44 -05:00
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)
2026-09-02 08:18:46 -05:00
it = 1; // posicion 3
// rsp.PrintCintaTypes(0, 20);
//--- Encrypt
while(it.IsValid())
{
it["CIPHERTEXT"].Value().HexToBytes(chiper);
it["PLAINTEXT"].Value().HexToBytes(bytes);
it["KEY"].Value().HexToBytes(key);
2026-09-02 07:22:44 -05:00
if(!m_aes.Init(key))
{
msg = StringFormat("[ENC] Fallo al setear key, counter=%d, file:\n%s", it.ReadPars(),
m_arr_fn[z]);
return false;
}
m_aes.Cifrar(bytes);
if(!CRSPNode::BytesEq(bytes, chiper))
{
2026-09-02 07:22:44 -05:00
msg = StringFormat("(Encrypt) 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();
}
2026-09-02 08:18:46 -05:00
//--- rotamos
it.HashPos(2, "CIPHERTEXT");
it.HashPos(3, "PLAINTEXT");
// 2 = 3616922305531329600 | 3 = 1120525493790227457
//---
it.ResetLast();
2026-09-02 08:18:46 -05:00
// ahora mismo en [cor]
it += 1; // saltamos cor (triplete)
// ahora si empezamos
//--- 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))
{
2026-09-02 07:22:44 -05:00
msg = StringFormat("(Decrypt) 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();
}
//Print("pass");
// rotamos (volvemos a su posicion original)
it.HashPos(3, "CIPHERTEXT");
it.HashPos(2, "PLAINTEXT");
}
//---
return true;
}
2026-08-25 20:10:08 -05:00
2026-08-26 09:31:56 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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);
2026-09-02 07:22:44 -05:00
if(!rsp.AutoParseByFileExt(ext))
2026-08-26 09:31:56 -05:00
{
msg = StringFormat("Fallo al parser .rsp, last err = %s", EnumToString(rsp.LastErr()));
return false;
}
//--- movemos
it.RecalcLen(); // recaluclso del len (para el contexto)
2026-09-02 08:18:46 -05:00
it = 1; // posicion 3
2026-08-26 09:31:56 -05:00
//--- 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();
}
//--- rotamos
it.HashPos(3, "CIPHERTEXT");
it.HashPos(4, "PLAINTEXT");
2026-08-26 09:31:56 -05:00
//---
it.ResetLast();
// ahora mismo en meta
it += 1;
2026-08-26 09:31:56 -05:00
//--- 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();
}
// rotamos (volvemos a su posicion original)
it.HashPos(4, "CIPHERTEXT");
it.HashPos(3, "PLAINTEXT");
2026-08-26 09:31:56 -05:00
}
//---
return true;
}
2026-08-25 09:19:11 -05:00
//---
}
//+------------------------------------------------------------------+