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