void ZeroKnowledgeTest(Library* lib, bool test_bit_flip) { QScopedPointer<DiffieHellman> dhA(lib->CreateDiffieHellman()); QScopedPointer<DiffieHellman> dhB(lib->CreateDiffieHellman()); QScopedPointer<DiffieHellman> dhC(lib->CreateDiffieHellman()); QByteArray shared_A_B = dhA->GetSharedSecret(dhB->GetPublicComponent()); QByteArray shared_B_A = dhB->GetSharedSecret(dhA->GetPublicComponent()); EXPECT_EQ(shared_A_B, shared_B_A); QByteArray proof_A = dhA->ProveSharedSecret(dhB->GetPublicComponent()); QByteArray verif_A = dhC->VerifySharedSecret(dhA->GetPublicComponent(), dhB->GetPublicComponent(), proof_A); EXPECT_EQ(shared_A_B, verif_A); if(test_bit_flip) { int idx = proof_A.size()-1; proof_A[idx] = !proof_A[idx]; QByteArray verif_A2 = dhC->VerifySharedSecret(dhA->GetPublicComponent(), dhB->GetPublicComponent(), proof_A); EXPECT_EQ(QByteArray(), verif_A2); } }
ustring PubAddr::encode(ustring pubKA, ustring privKB , ustring pubKB ,ustring plain) { OID CURVE = secp256k1(); AutoSeededRandomPool rng; ECDH < ECP >::Domain dhA(CURVE), dhB(CURVE); SecByteBlock privB(privKB.c_str(), dhA.PrivateKeyLength()); SecByteBlock pubA(pubKA.c_str(), dhB.PublicKeyLength()); if (dhA.AgreedValueLength() != dhB.AgreedValueLength()) throw runtime_error("Shared shared size mismatch"); SecByteBlock sharedA(dhA.AgreedValueLength()), sharedB(dhB.AgreedValueLength()); if (!dhA.Agree(sharedA, privB, pubA)) throw runtime_error("Failed to reach shared secret (A)"); Integer ssa, ssb; ssa.Decode(sharedA.BytePtr(), sharedA.SizeInBytes()); uint8_t H[CryptoPP::SHA512::DIGESTSIZE]; CryptoPP::SHA512 hash; hash.CalculateDigest(H, sharedA.BytePtr(), sharedA.SizeInBytes()); AutoSeededRandomPool prng; byte key[32]; memcpy(key, H, sizeof(key)); byte Hkey[32]; memcpy(Hkey, &(H[32]), sizeof(Hkey)); byte iv[16]; prng.GenerateBlock(iv, sizeof(iv)); string SPlain = plain.toString(), encoded; try { CBC_Mode< AES >::Encryption e; e.SetKeyWithIV(key, sizeof(key), iv); // The StreamTransformationFilter removes // padding as required. StringSource s(SPlain, true, new StreamTransformationFilter(e, new StringSink(encoded) ) // StreamTransformationFilter ); // StringSource } catch (const CryptoPP::Exception& e) { throw runtime_error(e.what()); } ustring result; result.append(iv, 16); result.appendInt16(714); result.appendInt16(32); result.append(pubKB.c_str() + 1, 32); result.appendInt16(32); result.append(pubKB.c_str() + 33, 32); result.fromString(encoded); string HMacPlain; HMacPlain += result.toString(); string mac; try { HMAC<SHA256> hmac(Hkey, 32); StringSource s(HMacPlain, true, new HashFilter(hmac, new StringSink(mac) ) ); } catch (const CryptoPP::Exception& e) { throw runtime_error(e.what()); } result.fromString(mac); return result; }
ustring PubAddr::decode(ustring data, ustring privK) { unsigned int p = 0; ustring IV = data.getUstring(16, p); unsigned int curveType = data.getInt16(p); unsigned int Xlen = data.getInt16(p); ustring X = data.getUstring(Xlen, p); unsigned int Ylen = data.getInt16(p); ustring Y = data.getUstring(Ylen, p); ustring cipherText = data.getUstring(data.size() - (p + 32), p); ustring MAC = data.getUstring(32, p); ustring pubK; pubK += 0x04; pubK += X; pubK += Y; OID CURVE = secp256k1(); AutoSeededRandomPool rng; ECDH < ECP >::Domain dhA(CURVE), dhB(CURVE); SecByteBlock privA(privK.c_str(), dhA.PrivateKeyLength()); SecByteBlock pubB(pubK.c_str(), dhB.PublicKeyLength()); if (dhA.AgreedValueLength() != dhB.AgreedValueLength()) { throw runtime_error("Shared shared size mismatch"); } SecByteBlock sharedA(dhA.AgreedValueLength()), sharedB(dhB.AgreedValueLength()); if (!dhA.Agree(sharedA, privA, pubB)) throw runtime_error("Failed to reach shared secret (A)"); Integer ssa, ssb; ssa.Decode(sharedA.BytePtr(), sharedA.SizeInBytes()); uint8_t H[CryptoPP::SHA512::DIGESTSIZE]; CryptoPP::SHA512 hash; hash.CalculateDigest(H, sharedA.BytePtr(), sharedA.SizeInBytes()); AutoSeededRandomPool prng; byte key[32]; memcpy(key, H, sizeof(key)); byte Hkey[32]; memcpy(Hkey, &(H[32]), sizeof(Hkey)); byte iv[16]; memcpy(iv, IV.c_str(), IV.size()); string cipher = cipherText.toString(), encoded, recovered; string HMacPlain; p = 0; HMacPlain += data.getString(data.size()-32,p); string mac; try { HMAC<SHA256> hmac(Hkey, 32); StringSource s(HMacPlain, true, new HashFilter(hmac, new StringSink(mac) ) ); } catch (const CryptoPP::Exception& e) { throw runtime_error(e.what()); } if (mac != MAC.toString()) throw runtime_error("mac doesnt match"); try { CBC_Mode< AES >::Decryption d; d.SetKeyWithIV(key, sizeof(key), iv); // The StreamTransformationFilter removes // padding as required. StringSource s(cipher, true, new StreamTransformationFilter(d, new StringSink(recovered) ) // StreamTransformationFilter ); // StringSource } catch (const CryptoPP::Exception& e) { throw runtime_error(e.what()); } ustring result; result.fromString(recovered); return result; }