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; }
packet_pubkey Addr::encodePubKey() { std::shared_lock<std::shared_timed_mutex> mlock(this->mutex_); packet_pubkey pubkey; time_t ltime = std::time(nullptr); this->lastPubKeyRequest = ltime; std::random_device rd; std::mt19937 engine(rd()); std::uniform_int_distribution<int> distribution(-300, 300); int random = distribution(engine); time_t TTL = 4 * 24 * 60 * 60 + random; //4 days +- 5 min ltime = ltime + TTL; pubkey.objectType = 1; pubkey.Time = ltime; pubkey.stream = this->getStream(); pubkey.version = 4; pubkey.encodePayload(); ustring plain; OID CURVE = secp256k1(); AutoSeededRandomPool rng; ECDH < ECP >::Domain dhA(CURVE); //generating ephemeral key pair SecByteBlock privA(dhA.PrivateKeyLength()), pubA(dhA.PublicKeyLength()); dhA.GenerateKeyPair(rng, privA, pubA); ustring pubEKey; pubEKey.append(pubA.data(), pubA.size()); ustring privEKey; privEKey.append(privA.data(), privA.size()); plain.appendInt32(1); //bitfiled 1 not yet integrated plain.append(this->pubSigningKey.c_str() + 1, 64); plain.append(this->pubEncryptionKey.c_str() + 1, 64); plain.appendVarInt_B(this->nonce_trials); plain.appendVarInt_B(this->extra_bytes); AutoSeededRandomPool prng; ECDSA<ECP, SHA1>::PrivateKey privateKey; Integer x; x.Decode(this->getPrivSigningKey().c_str(), this->getPrivSigningKey().size()); privateKey.Initialize(CURVE, x); ECDSA<ECP, SHA1>::Signer signer(privateKey); string signature; string mess; ustring mess1; unsigned int i = 8; mess1.appendInt64(pubkey.message_payload.getInt64(i)); mess1.appendInt32(pubkey.message_payload.getInt32(i)); mess1.appendVarInt_B(pubkey.message_payload.getVarInt_B(i)); mess1.appendVarInt_B(pubkey.message_payload.getVarInt_B(i)); mess1 += this->getTag(); mess += mess1.toString(); mess += plain.toString(); StringSource ss(mess, true /*pump all*/, new SignerFilter(prng, signer, new StringSink(signature) ) // SignerFilter ); // StringSource //DER encoding Integer r, s; StringStore store(signature); r.Decode(store, signature.size() / 2); s.Decode(store, signature.size() / 2); string sign; StringSink sink(sign); DERSequenceEncoder seq(sink); r.DEREncode(seq); s.DEREncode(seq); seq.MessageEnd(); //end conversion plain.appendVarInt_B(sign.size()); plain.append((unsigned char*)sign.c_str(), sign.size()); ECIES<ECP>::PrivateKey priv; ustring pubK = this->getPubOfPriv(this->getTagE()); //Integer e; //e.Decode(this->getTagE().c_str(), 32); //priv.Initialize(CURVE, e); //ECIES<ECP>::PublicKey pub; //priv.MakePublicKey(pub); //const ECP::Point& qq = pub.GetPublicElement(); //string pubS; //StringSink sinkK(pubS); //qq.x.Encode(sinkK, 32); //qq.y.Encode(sinkK, 32); //ustring pubK; //pubK += 0x04; //pubK.fromString(pubS); ustring encoded = this->encode(pubK, privEKey, pubEKey, plain); pubkey.tag = this->getTag(); pubkey.encrypted = encoded; pubkey.encodeObject(); return pubkey; }