const vector<unsigned char> CryptoPpDlogZpSafePrime::decodeGroupElementToByteArray(GroupElement * groupElement) { ZpSafePrimeElementCryptoPp * zp_element = dynamic_cast<ZpSafePrimeElementCryptoPp *>(groupElement); if (!(zp_element)) throw invalid_argument("element type doesn't match the group type"); //Given a group element y, find the two inverses z,-z. Take z to be the value between 1 and (p-1)/2. Return s=z-1 biginteger y = zp_element->getElementValue(); biginteger p = ((ZpGroupParams * ) groupParams)->getP(); MathAlgorithms::SquareRootResults roots = MathAlgorithms::sqrtModP_3_4(y, p); biginteger goodRoot; biginteger halfP = (p - 1) / 2; if (roots.getRoot1()>1 && roots.getRoot1() < halfP) goodRoot = roots.getRoot1(); else goodRoot = roots.getRoot2(); goodRoot -= 1; CryptoPP::Integer cpi = biginteger_to_cryptoppint(goodRoot); int len = ceil((cpi.BitCount() + 1) / 8.0); //ceil(find_log2_floor(goodRoot) / 8.0); byte * output = new byte[len]; cpi.Encode(output, len); vector<byte> res; // Remove the padding byte at the most significant position (that was added while encoding) for (int i = 1; i < len; ++i) res.push_back(output[i]); return res; }
bool CryptoECDSA::VerifyPublicKeyValid(SecureBinaryData const & pubKey65) { if(CRYPTO_DEBUG) { cout << "BinPub: " << pubKey65.toHexStr() << endl; } // Basically just copying the ParsePublicKey method, but without // the assert that would throw an error from C++ SecureBinaryData pubXbin(pubKey65.getSliceRef( 1,32)); SecureBinaryData pubYbin(pubKey65.getSliceRef(33,32)); CryptoPP::Integer pubX; CryptoPP::Integer pubY; pubX.Decode(pubXbin.getPtr(), pubXbin.getSize(), UNSIGNED); pubY.Decode(pubYbin.getPtr(), pubYbin.getSize(), UNSIGNED); BTC_ECPOINT publicPoint(pubX, pubY); // Initialize the public key with the ECP point just created BTC_PUBKEY cppPubKey; cppPubKey.Initialize(CryptoPP::ASN1::secp256k1(), publicPoint); // Validate the public key -- not sure why this needs a PRNG static BTC_PRNG prng; return cppPubKey.Validate(prng, 3); }
SecureBinaryData CryptoECDSA::SerializePrivateKey(BTC_PRIVKEY const & privKey) { CryptoPP::Integer privateExp = privKey.GetPrivateExponent(); SecureBinaryData privKeyData(32); privateExp.Encode(privKeyData.getPtr(), privKeyData.getSize(), UNSIGNED); return privKeyData; }
std::vector<byte> encode_signature(CryptoPP::Integer r, CryptoPP::Integer s) { std::vector<byte> signature; signature.resize(64); r.Encode(signature.data(), 32); s.Encode(signature.data() + 32, 32); return signature; }
BTC_PRIVKEY CryptoECDSA::ParsePrivateKey(SecureBinaryData const & privKeyData) { BTC_PRIVKEY cppPrivKey; CryptoPP::Integer privateExp; privateExp.Decode(privKeyData.getPtr(), privKeyData.getSize(), UNSIGNED); cppPrivKey.Initialize(CryptoPP::ASN1::secp256k1(), privateExp); return cppPrivKey; }
SecureBinaryData CryptoECDSA::SerializePublicKey(BTC_PUBKEY const & pubKey) { BTC_ECPOINT publicPoint = pubKey.GetPublicElement(); CryptoPP::Integer pubX = publicPoint.x; CryptoPP::Integer pubY = publicPoint.y; SecureBinaryData pubData(65); pubData.fill(0x04); // we fill just to set the first byte... pubX.Encode(pubData.getPtr()+1, 32, UNSIGNED); pubY.Encode(pubData.getPtr()+33, 32, UNSIGNED); return pubData; }
CryptoPP::ECP::Point Mul (const CryptoPP::ECP::Point& p, const CryptoPP::Integer& e) const { CryptoPP::ECP::Point res {0, 1}; if (!e.IsZero ()) { auto bitCount = e.BitCount (); for (int i = bitCount - 1; i >= 0; i--) { res = Sum (res, res); if (e.GetBit (i)) res = Sum (res, p); } } return res; }
std::string security::str(const CryptoPP::Integer& input) { const auto input_size = input.MinEncodedSize(); CryptoPP::SecByteBlock block(input_size); input.Encode(block.BytePtr(), input_size); return str(block); // NOTE: CryptoPP::Integer has a weird ostream format (uses prefixes to specify numeric base) // /*std::ostringstream oss; oss << std::hex << input; return oss.str();*/ }
///////////////////////////////////////////////////////////////////////////// // Deterministically generate new public key using a chaincode SecureBinaryData CryptoECDSA::ComputeChainedPublicKey( SecureBinaryData const & binPubKey, SecureBinaryData const & chainCode, SecureBinaryData* multiplierOut) { if(CRYPTO_DEBUG) { cout << "ComputeChainedPUBLICKey:" << endl; cout << " BinPub: " << binPubKey.toHexStr() << endl; cout << " BinChn: " << chainCode.toHexStr() << endl; } static SecureBinaryData SECP256K1_ORDER_BE = SecureBinaryData::CreateFromHex( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); // Added extra entropy to chaincode by xor'ing with hash256 of pubkey BinaryData chainMod = binPubKey.getHash256(); BinaryData chainOrig = chainCode.getRawCopy(); BinaryData chainXor(32); for(uint8_t i=0; i<8; i++) { uint8_t offset = 4*i; *(uint32_t*)(chainXor.getPtr()+offset) = *(uint32_t*)( chainMod.getPtr()+offset) ^ *(uint32_t*)(chainOrig.getPtr()+offset); } // Parse the chaincode as a big-endian integer CryptoPP::Integer mult; mult.Decode(chainXor.getPtr(), chainXor.getSize(), UNSIGNED); // "new" init as "old", to make sure it's initialized on the correct curve BTC_PUBKEY oldPubKey = ParsePublicKey(binPubKey); BTC_PUBKEY newPubKey = ParsePublicKey(binPubKey); // Let Crypto++ do the EC math for us, serialize the new public key newPubKey.SetPublicElement( oldPubKey.ExponentiatePublicElement(mult) ); if(multiplierOut != NULL) (*multiplierOut) = SecureBinaryData(chainXor); //LOGINFO << "Computed new chained public key using:"; //LOGINFO << " Public key: " << binPubKey.toHexStr().c_str(); //LOGINFO << " PubKeyHash: " << chainMod.toHexStr().c_str(); //LOGINFO << " Chaincode: " << chainOrig.toHexStr().c_str(); //LOGINFO << " Multiplier: " << chainXor.toHexStr().c_str(); return CryptoECDSA::SerializePublicKey(newPubKey); }
bool verify(CryptoPP::ECPPoint Q, byte *message, unsigned message_length, CryptoPP::Integer r, CryptoPP::Integer s){ auto ec = common::ec_parameters().GetCurve(); auto G = common::ec_parameters().GetSubgroupGenerator(); auto n = common::ec_parameters().GetGroupOrder(); Integer z = hash_m_to_int(message, message_length, n.ByteCount()); // verify if (Q == ec.Identity()){ cerr << "Q == O" << endl; return false; } if (!(ec.Multiply(n, Q) == ec.Identity())){ cerr << "n x Q != O" << endl; return false; } if (r <= 0 || r >= n){ cerr << "incorrect r" << endl; return false; } if (s <= 0 || s >= n){ cerr << "incorrect s" << endl; return false; } Integer w = s.InverseMod(n); Integer u1 = a_times_b_mod_c(z, w, n); Integer u2 = a_times_b_mod_c(r, w, n); ECPPoint P2 = ec.Add(ec.Multiply(u1, G), ec.Multiply(u2, Q)); if (P2.x != r){ cerr << "P2.x != r" << endl; return false; } return true; }
bool CryptoECDSA::ECVerifyPoint(BinaryData const & x, BinaryData const & y) { BTC_PUBKEY cppPubKey; CryptoPP::Integer pubX; CryptoPP::Integer pubY; pubX.Decode(x.getPtr(), x.getSize(), UNSIGNED); pubY.Decode(y.getPtr(), y.getSize(), UNSIGNED); BTC_ECPOINT publicPoint(pubX, pubY); // Initialize the public key with the ECP point just created cppPubKey.Initialize(CryptoPP::ASN1::secp256k1(), publicPoint); // Validate the public key -- not sure why this needs a PRNG BTC_PRNG prng; return cppPubKey.Validate(prng, 3); }
template<> unsigned long Read(CryptoPP::Integer & val) { std::vector<unsigned char> data; unsigned long rValue = SimpleReader::Read(data); val.Decode(&data[0], data.size()); return rValue; }
CryptoPP::Integer RecoverX (const CryptoPP::Integer& y) const { auto y2 = y.Squared (); auto xx = (y2 - CryptoPP::Integer::One())*(d*y2 + CryptoPP::Integer::One()).InverseMod (q); auto x = a_exp_b_mod_c (xx, (q + CryptoPP::Integer (3)).DividedBy (8), q); if (!(x.Squared () - xx).Modulo (q).IsZero ()) x = a_times_b_mod_c (x, I, q); if (x.IsOdd ()) x = q - x; return x; }
CK_RV CKKeyObject::CopyInteger(CK_ATTRIBUTE& attribute, const CryptoPP::Integer& intValue) const { CK_ULONG intSize = intValue.MinEncodedSize(); if (attribute.pValue == NULL_PTR) { attribute.ulValueLen = intSize; } else if (attribute.ulValueLen < intSize) { attribute.ulValueLen = (CK_ULONG)-1; return CKR_BUFFER_TOO_SMALL; } else { attribute.ulValueLen = intSize; intValue.Encode((byte*)attribute.pValue, attribute.ulValueLen); } return CKR_OK; }
BTC_PUBKEY CryptoECDSA::ParsePublicKey(SecureBinaryData const & pubKeyX32B, SecureBinaryData const & pubKeyY32B) { BTC_PUBKEY cppPubKey; CryptoPP::Integer pubX; CryptoPP::Integer pubY; pubX.Decode(pubKeyX32B.getPtr(), pubKeyX32B.getSize(), UNSIGNED); pubY.Decode(pubKeyY32B.getPtr(), pubKeyY32B.getSize(), UNSIGNED); BTC_ECPOINT publicPoint(pubX, pubY); // Initialize the public key with the ECP point just created cppPubKey.Initialize(CryptoPP::ASN1::secp256k1(), publicPoint); // Validate the public key -- not sure why this needs a PRNG BTC_PRNG prng; assert(cppPubKey.Validate(prng, 3)); return cppPubKey; }
CryptoPP::ECP CryptoECDSA::Get_secp256k1_ECP(void) { static bool firstRun = true; static CryptoPP::Integer intN; static CryptoPP::Integer inta; static CryptoPP::Integer intb; static BinaryData N; static BinaryData a; static BinaryData b; if(firstRun) { firstRun = false; N = BinaryData::CreateFromHex( "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"); a = BinaryData::CreateFromHex( "0000000000000000000000000000000000000000000000000000000000000000"); b = BinaryData::CreateFromHex( "0000000000000000000000000000000000000000000000000000000000000007"); intN.Decode( N.getPtr(), N.getSize(), UNSIGNED); inta.Decode( a.getPtr(), a.getSize(), UNSIGNED); intb.Decode( b.getPtr(), b.getSize(), UNSIGNED); } return CryptoPP::ECP(intN, inta, intb); }
SecureBinaryData CryptoECDSA::InvMod(const SecureBinaryData& m) { static BinaryData N = BinaryData::CreateFromHex( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); CryptoPP::Integer cppM; CryptoPP::Integer cppModulo; cppM.Decode(m.getPtr(), m.getSize(), UNSIGNED); cppModulo.Decode(N.getPtr(), N.getSize(), UNSIGNED); CryptoPP::Integer cppResult = cppM.InverseMod(cppModulo); SecureBinaryData result(32); cppResult.Encode(result.getPtr(), result.getSize(), UNSIGNED); return result; }
bool CryptoECDSA::VerifyPublicKeyValid(SecureBinaryData const & pubKey) { if(CRYPTO_DEBUG) { cout << "BinPub: " << pubKey.toHexStr() << endl; } SecureBinaryData keyToCheck(65); // To support compressed keys, we'll just check to see if a key is compressed // and then decompress it. if(pubKey.getSize() == 33) { keyToCheck = UncompressPoint(pubKey); } else { keyToCheck = pubKey; } // Basically just copying the ParsePublicKey method, but without // the assert that would throw an error from C++ SecureBinaryData pubXbin(keyToCheck.getSliceRef( 1,32)); SecureBinaryData pubYbin(keyToCheck.getSliceRef(33,32)); CryptoPP::Integer pubX; CryptoPP::Integer pubY; pubX.Decode(pubXbin.getPtr(), pubXbin.getSize(), UNSIGNED); pubY.Decode(pubYbin.getPtr(), pubYbin.getSize(), UNSIGNED); BTC_ECPOINT publicPoint(pubX, pubY); // Initialize the public key with the ECP point just created BTC_PUBKEY cppPubKey; cppPubKey.Initialize(CryptoPP::ASN1::secp256k1(), publicPoint); // Validate the public key -- not sure why this needs a PRNG BTC_PRNG prng; return cppPubKey.Validate(prng, 3); }
void CEncryptedStreamSocket::StartNegotiation(bool bOutgoing) { //printf("Starting socket negotiation\n"); if (!bOutgoing) { //printf("Incoming connection negotiation on %s\n", (const char*) unicode2char(DbgGetIPString())); m_NegotiatingState = ONS_BASIC_CLIENTA_RANDOMPART; m_StreamCryptState = ECS_NEGOTIATING; m_nReceiveBytesWanted = 4; } else if (m_StreamCryptState == ECS_PENDING) { //printf("Socket is client.pending on negotiation\n"); CMemFile fileRequest(29); const uint8_t bySemiRandomNotProtocolMarker = GetSemiRandomNotProtocolMarker(); fileRequest.WriteUInt8(bySemiRandomNotProtocolMarker); fileRequest.WriteUInt32(m_nRandomKeyPart); fileRequest.WriteUInt32(MAGICVALUE_SYNC); const uint8_t bySupportedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version fileRequest.WriteUInt8(bySupportedEncryptionMethod); fileRequest.WriteUInt8(bySupportedEncryptionMethod); // so we also prefer this one uint8_t byPadding = (uint8_t)(GetRandomUint8() % (thePrefs::GetCryptTCPPaddingLength() + 1)); fileRequest.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) { fileRequest.WriteUInt8(GetRandomUint8()); } m_NegotiatingState = ONS_BASIC_CLIENTB_MAGICVALUE; m_StreamCryptState = ECS_NEGOTIATING; m_nReceiveBytesWanted = 4; SendNegotiatingData(fileRequest.GetRawBuffer(), (uint32_t)fileRequest.GetLength(), 5); } else if (m_StreamCryptState == ECS_PENDING_SERVER) { //printf("Socket is server.pending on negotiation\n"); CMemFile fileRequest(113); const uint8_t bySemiRandomNotProtocolMarker = GetSemiRandomNotProtocolMarker(); fileRequest.WriteUInt8(bySemiRandomNotProtocolMarker); m_cryptDHA.Randomize((CryptoPP::AutoSeededRandomPool&)GetRandomPool(), DHAGREEMENT_A_BITS); // our random a wxASSERT( m_cryptDHA.MinEncodedSize() <= DHAGREEMENT_A_BITS / 8 ); CryptoPP::Integer cryptDHPrime((byte*)dh768_p, PRIMESIZE_BYTES); // our fixed prime // calculate g^a % p CryptoPP::Integer cryptDHGexpAmodP = a_exp_b_mod_c(CryptoPP::Integer(2), m_cryptDHA, cryptDHPrime); wxASSERT( m_cryptDHA.MinEncodedSize() <= PRIMESIZE_BYTES ); // put the result into a buffer uint8_t aBuffer[PRIMESIZE_BYTES]; cryptDHGexpAmodP.Encode(aBuffer, PRIMESIZE_BYTES); fileRequest.Write(aBuffer, PRIMESIZE_BYTES); uint8 byPadding = (uint8)(GetRandomUint8() % 16); // add random padding fileRequest.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) { fileRequest.WriteUInt8(GetRandomUint8()); } m_NegotiatingState = ONS_BASIC_SERVER_DHANSWER; m_StreamCryptState = ECS_NEGOTIATING; m_nReceiveBytesWanted = 96; SendNegotiatingData(fileRequest.GetRawBuffer(), (uint32_t)fileRequest.GetLength(), (uint32_t)fileRequest.GetLength()); } else { wxFAIL; m_StreamCryptState = ECS_NONE; return; } }
void CEncryptedStreamSocket::StartNegotiation(bool bOutgoing){ if (!bOutgoing){ m_NegotiatingState = ONS_BASIC_CLIENTA_RANDOMPART; m_StreamCryptState = ECS_NEGOTIATING; m_nReceiveBytesWanted = 4; } else if (m_StreamCryptState == ECS_PENDING){ CSafeMemFile fileRequest(29); const uint8_t bySemiRandomNotProtocolMarker = GetSemiRandomNotProtocolMarker(); fileRequest.WriteUInt8(bySemiRandomNotProtocolMarker); fileRequest.WriteUInt32(m_nRandomKeyPart); fileRequest.WriteUInt32(MAGICVALUE_SYNC); const uint8_t bySupportedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version fileRequest.WriteUInt8(bySupportedEncryptionMethod); fileRequest.WriteUInt8(bySupportedEncryptionMethod); // so we also prefer this one uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % (thePrefs.GetCryptTCPPaddingLength() + 1)); fileRequest.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) fileRequest.WriteUInt8(cryptRandomGen.GenerateByte()); m_NegotiatingState = ONS_BASIC_CLIENTB_MAGICVALUE; m_StreamCryptState = ECS_NEGOTIATING; m_nReceiveBytesWanted = 4; SendNegotiatingData(fileRequest.GetBuffer(), (uint32_t)fileRequest.GetLength(), 5); } else if (m_StreamCryptState == ECS_PENDING_SERVER){ CSafeMemFile fileRequest(113); const uint8_t bySemiRandomNotProtocolMarker = GetSemiRandomNotProtocolMarker(); fileRequest.WriteUInt8(bySemiRandomNotProtocolMarker); m_cryptDHA.Randomize(cryptRandomGen, DHAGREEMENT_A_BITS); // our random a ASSERT( m_cryptDHA.MinEncodedSize() <= DHAGREEMENT_A_BITS / 8 ); CryptoPP::Integer cryptDHPrime((byte*)dh768_p, PRIMESIZE_BYTES); // our fixed prime // calculate g^a % p CryptoPP::Integer cryptDHGexpAmodP = CryptoPP::a_exp_b_mod_c(CryptoPP::Integer(2), m_cryptDHA, cryptDHPrime); ASSERT( m_cryptDHA.MinEncodedSize() <= PRIMESIZE_BYTES ); // put the result into a buffer uchar aBuffer[PRIMESIZE_BYTES]; cryptDHGexpAmodP.Encode(aBuffer, PRIMESIZE_BYTES); fileRequest.Write(aBuffer, PRIMESIZE_BYTES); uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % 16); // add random padding fileRequest.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) fileRequest.WriteUInt8(cryptRandomGen.GenerateByte()); m_NegotiatingState = ONS_BASIC_SERVER_DHANSWER; m_StreamCryptState = ECS_NEGOTIATING; m_nReceiveBytesWanted = 96; SendNegotiatingData(fileRequest.GetBuffer(), (uint32_t)fileRequest.GetLength(), (uint32_t)fileRequest.GetLength()); } else{ ASSERT( false ); m_StreamCryptState = ECS_NONE; return; } }
void Reseeder::LoadCertificate (const std::string& filename) { std::ifstream s(filename, std::ifstream::binary); if (s.is_open ()) { s.seekg (0, std::ios::end); size_t len = s.tellg (); s.seekg (0, std::ios::beg); char buf[2048]; s.read (buf, len); std::string cert (buf, len); // assume file in pem format auto pos1 = cert.find (CERTIFICATE_HEADER); auto pos2 = cert.find (CERTIFICATE_FOOTER); if (pos1 == std::string::npos || pos2 == std::string::npos) { LogPrint (eLogError, "Malformed certificate file"); return; } pos1 += strlen (CERTIFICATE_HEADER); pos2 -= pos1; std::string base64 = cert.substr (pos1, pos2); CryptoPP::ByteQueue queue; CryptoPP::Base64Decoder decoder; // regular base64 rather than I2P decoder.Attach (new CryptoPP::Redirector (queue)); decoder.Put ((const uint8_t *)base64.data(), base64.length()); decoder.MessageEnd (); // extract X.509 CryptoPP::BERSequenceDecoder x509Cert (queue); CryptoPP::BERSequenceDecoder tbsCert (x509Cert); // version uint32_t ver; CryptoPP::BERGeneralDecoder context (tbsCert, 0xa0); CryptoPP::BERDecodeUnsigned<uint32_t>(context, ver, CryptoPP::INTEGER); LogPrint (eLogInfo, ver); // serial CryptoPP::Integer serial; serial.BERDecode(tbsCert); // signature CryptoPP::BERSequenceDecoder signature (tbsCert); signature.SkipAll(); // issuer CryptoPP::BERSequenceDecoder issuer (tbsCert); issuer.SkipAll(); // validity CryptoPP::BERSequenceDecoder validity (tbsCert); validity.SkipAll(); // subject CryptoPP::BERSequenceDecoder subject (tbsCert); subject.SkipAll(); // public key CryptoPP::BERSequenceDecoder publicKey (tbsCert); publicKey.SkipAll(); tbsCert.SkipAll(); x509Cert.SkipAll(); } else LogPrint (eLogError, "Can't open certificate file ", filename); }
int CEncryptedStreamSocket::Negotiate(const uchar* pBuffer, uint32_t nLen){ uint32_t nRead = 0; ASSERT( m_nReceiveBytesWanted > 0 ); try{ while (m_NegotiatingState != ONS_COMPLETE && m_nReceiveBytesWanted > 0){ if (m_nReceiveBytesWanted > 512){ ASSERT( false ); return 0; } if (m_pfiReceiveBuffer == NULL){ BYTE* pReceiveBuffer = (BYTE*)malloc(512); // use a fixed size buffer if (pReceiveBuffer == NULL) AfxThrowMemoryException(); m_pfiReceiveBuffer = new CSafeMemFile(pReceiveBuffer, 512); } const uint32_t nToRead = min(nLen - nRead, m_nReceiveBytesWanted); m_pfiReceiveBuffer->Write(pBuffer + nRead, nToRead); nRead += nToRead; m_nReceiveBytesWanted -= nToRead; if (m_nReceiveBytesWanted > 0) return nRead; const uint32_t nCurrentBytesLen = (uint32_t)m_pfiReceiveBuffer->GetPosition(); if (m_NegotiatingState != ONS_BASIC_CLIENTA_RANDOMPART && m_NegotiatingState != ONS_BASIC_SERVER_DHANSWER){ // don't have the keys yet BYTE* pCryptBuffer = m_pfiReceiveBuffer->Detach(); RC4Crypt(pCryptBuffer, pCryptBuffer, nCurrentBytesLen, m_pRC4ReceiveKey); m_pfiReceiveBuffer->Attach(pCryptBuffer, 512); } m_pfiReceiveBuffer->SeekToBegin(); switch (m_NegotiatingState){ case ONS_NONE: // would be a bug ASSERT( false ); return 0; case ONS_BASIC_CLIENTA_RANDOMPART:{ ASSERT( m_pRC4ReceiveKey == NULL ); uchar achKeyData[21]; md4cpy(achKeyData, thePrefs.GetUserHash()); achKeyData[16] = MAGICVALUE_REQUESTER; m_pfiReceiveBuffer->Read(achKeyData + 17, 4); // random key part sent from remote client MD5Sum md5(achKeyData, sizeof(achKeyData)); m_pRC4ReceiveKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); achKeyData[16] = MAGICVALUE_SERVER; md5.Calculate(achKeyData, sizeof(achKeyData)); m_pRC4SendKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); m_NegotiatingState = ONS_BASIC_CLIENTA_MAGICVALUE; m_nReceiveBytesWanted = 4; break; } case ONS_BASIC_CLIENTA_MAGICVALUE:{ uint32_t dwValue = m_pfiReceiveBuffer->ReadUInt32(); if (dwValue == MAGICVALUE_SYNC){ // yup, the one or the other way it worked, this is an encrypted stream //DEBUG_ONLY( DebugLog(_T("Received proper magic value, clientIP: %s"), DbgGetIPString()) ); // set the receiver key m_NegotiatingState = ONS_BASIC_CLIENTA_METHODTAGSPADLEN; m_nReceiveBytesWanted = 3; } else{ DebugLogError(_T("CEncryptedStreamSocket: Received wrong magic value from clientIP %s on a supposly encrytped stream / Wrong Header"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return (-1); } break; } case ONS_BASIC_CLIENTA_METHODTAGSPADLEN: m_dbgbyEncryptionSupported = m_pfiReceiveBuffer->ReadUInt8(); m_dbgbyEncryptionRequested = m_pfiReceiveBuffer->ReadUInt8(); if (m_dbgbyEncryptionRequested != ENM_OBFUSCATION) AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Client %s preffered unsupported encryption method (%i)"), DbgGetIPString(), m_dbgbyEncryptionRequested); m_nReceiveBytesWanted = m_pfiReceiveBuffer->ReadUInt8(); m_NegotiatingState = ONS_BASIC_CLIENTA_PADDING; //if (m_nReceiveBytesWanted > 16) // AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Client %s sent more than 16 (%i) padding bytes"), DbgGetIPString(), m_nReceiveBytesWanted); if (m_nReceiveBytesWanted > 0) break; case ONS_BASIC_CLIENTA_PADDING:{ // ignore the random bytes, send the response, set status complete CSafeMemFile fileResponse(26); fileResponse.WriteUInt32(MAGICVALUE_SYNC); const uint8_t bySelectedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version, so no need to look which the other client preferred fileResponse.WriteUInt8(bySelectedEncryptionMethod); SOCKADDR_IN sockAddr = {0}; int nSockAddrLen = sizeof(sockAddr); GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen); const uint8_t byPaddingLen = theApp.serverconnect->AwaitingTestFromIP(sockAddr.sin_addr.S_un.S_addr) ? 16 : (thePrefs.GetCryptTCPPaddingLength() + 1); uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % byPaddingLen); fileResponse.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) fileResponse.WriteUInt8(static_cast<uint8_t>(rand() & 0xFF)); SendNegotiatingData(fileResponse.GetBuffer(), (uint32_t)fileResponse.GetLength()); m_NegotiatingState = ONS_COMPLETE; m_StreamCryptState = ECS_ENCRYPTING; //DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (incoming)"), DbgGetIPString()) ); break; } case ONS_BASIC_CLIENTB_MAGICVALUE:{ if (m_pfiReceiveBuffer->ReadUInt32() != MAGICVALUE_SYNC){ DebugLogError(_T("CEncryptedStreamSocket: EncryptedstreamSyncError: Client sent wrong Magic Value as answer, cannot complete handshake (%s)"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return (-1); } m_NegotiatingState = ONS_BASIC_CLIENTB_METHODTAGSPADLEN; m_nReceiveBytesWanted = 2; break; } case ONS_BASIC_CLIENTB_METHODTAGSPADLEN:{ m_dbgbyEncryptionMethodSet = m_pfiReceiveBuffer->ReadUInt8(); if (m_dbgbyEncryptionMethodSet != ENM_OBFUSCATION){ DebugLogError( _T("CEncryptedStreamSocket: Client %s set unsupported encryption method (%i), handshake failed"), DbgGetIPString(), m_dbgbyEncryptionMethodSet); OnError(ERR_ENCRYPTION); return (-1); } m_nReceiveBytesWanted = m_pfiReceiveBuffer->ReadUInt8(); m_NegotiatingState = ONS_BASIC_CLIENTB_PADDING; if (m_nReceiveBytesWanted > 0) break; } case ONS_BASIC_CLIENTB_PADDING: // ignore the random bytes, the handshake is complete m_NegotiatingState = ONS_COMPLETE; m_StreamCryptState = ECS_ENCRYPTING; //DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (outgoing)"), DbgGetIPString()) ); break; case ONS_BASIC_SERVER_DHANSWER:{ ASSERT( !m_cryptDHA.IsZero() ); uchar aBuffer[PRIMESIZE_BYTES + 1]; m_pfiReceiveBuffer->Read(aBuffer, PRIMESIZE_BYTES); CryptoPP::Integer cryptDHAnswer((byte*)aBuffer, PRIMESIZE_BYTES); CryptoPP::Integer cryptDHPrime((byte*)dh768_p, PRIMESIZE_BYTES); // our fixed prime CryptoPP::Integer cryptResult = CryptoPP::a_exp_b_mod_c(cryptDHAnswer, m_cryptDHA, cryptDHPrime); m_cryptDHA = 0; DEBUG_ONLY( ZeroMemory(aBuffer, sizeof(aBuffer)) ); ASSERT( cryptResult.MinEncodedSize() <= PRIMESIZE_BYTES ); // create the keys cryptResult.Encode(aBuffer, PRIMESIZE_BYTES); aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_REQUESTER; MD5Sum md5(aBuffer, sizeof(aBuffer)); m_pRC4SendKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_SERVER; md5.Calculate(aBuffer, sizeof(aBuffer)); m_pRC4ReceiveKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); m_NegotiatingState = ONS_BASIC_SERVER_MAGICVALUE; m_nReceiveBytesWanted = 4; break; } case ONS_BASIC_SERVER_MAGICVALUE:{ uint32_t dwValue = m_pfiReceiveBuffer->ReadUInt32(); if (dwValue == MAGICVALUE_SYNC){ // yup, the one or the other way it worked, this is an encrypted stream DebugLog(_T("Received proper magic value after DH-Agreement from Serverconnection IP: %s"), DbgGetIPString()); // set the receiver key m_NegotiatingState = ONS_BASIC_SERVER_METHODTAGSPADLEN; m_nReceiveBytesWanted = 3; } else{ DebugLogError(_T("CEncryptedStreamSocket: Received wrong magic value after DH-Agreement from Serverconnection"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return (-1); } break; } case ONS_BASIC_SERVER_METHODTAGSPADLEN: m_dbgbyEncryptionSupported = m_pfiReceiveBuffer->ReadUInt8(); m_dbgbyEncryptionRequested = m_pfiReceiveBuffer->ReadUInt8(); if (m_dbgbyEncryptionRequested != ENM_OBFUSCATION) AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Server %s preffered unsupported encryption method (%i)"), DbgGetIPString(), m_dbgbyEncryptionRequested); m_nReceiveBytesWanted = m_pfiReceiveBuffer->ReadUInt8(); m_NegotiatingState = ONS_BASIC_SERVER_PADDING; if (m_nReceiveBytesWanted > 16) AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Server %s sent more than 16 (%i) padding bytes"), DbgGetIPString(), m_nReceiveBytesWanted); if (m_nReceiveBytesWanted > 0) break; case ONS_BASIC_SERVER_PADDING:{ // ignore the random bytes (they are decrypted already), send the response, set status complete CSafeMemFile fileResponse(26); fileResponse.WriteUInt32(MAGICVALUE_SYNC); const uint8_t bySelectedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version, so no need to look which the other client preferred fileResponse.WriteUInt8(bySelectedEncryptionMethod); uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % 16); fileResponse.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) fileResponse.WriteUInt8(static_cast<uint8_t>(rand() & 0xFF)); m_NegotiatingState = ONS_BASIC_SERVER_DELAYEDSENDING; SendNegotiatingData(fileResponse.GetBuffer(), (uint32_t)fileResponse.GetLength(), 0, true); // don't actually send it right now, store it in our sendbuffer m_StreamCryptState = ECS_ENCRYPTING; DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished DH Obufscation handshake with Server %s"), DbgGetIPString()) ); break; } default: ASSERT( false ); } m_pfiReceiveBuffer->SeekToBegin(); } if (m_pfiReceiveBuffer != NULL) free(m_pfiReceiveBuffer->Detach()); delete m_pfiReceiveBuffer; m_pfiReceiveBuffer = NULL; return nRead; } catch(CFileException* error){ // can only be caused by a bug in negationhandling, not by the datastream error->Delete(); ASSERT( false ); OnError(ERR_ENCRYPTION); if (m_pfiReceiveBuffer != NULL) free(m_pfiReceiveBuffer->Detach()); delete m_pfiReceiveBuffer; m_pfiReceiveBuffer = NULL; return (-1); } }
int CEncryptedStreamSocket::Negotiate(const uint8* pBuffer, uint32 nLen) { uint32_t nRead = 0; wxASSERT( m_nReceiveBytesWanted > 0 ); //DumpMem(pBuffer, nLen, wxT("Negotiate buffer: ")); try { while (m_NegotiatingState != ONS_COMPLETE && m_nReceiveBytesWanted > 0) { if (m_nReceiveBytesWanted > 512) { wxFAIL; return 0; } const uint32_t nToRead = std::min(nLen - nRead, m_nReceiveBytesWanted); //printf("Reading %i bytes, add from %i position on %i position\n",nToRead, nRead, (int)m_pfiReceiveBuffer.GetPosition()); //DumpMem(pBuffer + nRead, nToRead, wxT("Recv Buffer: ")); m_pfiReceiveBuffer.Write(pBuffer + nRead, nToRead); nRead += nToRead; m_nReceiveBytesWanted -= nToRead; if (m_nReceiveBytesWanted > 0) { return nRead; } if (m_NegotiatingState != ONS_BASIC_CLIENTA_RANDOMPART && m_NegotiatingState != ONS_BASIC_SERVER_DHANSWER) { // We have the keys, decrypt //printf("We have the keys, so decrypt away on %s\n", (const char*) unicode2char(DbgGetIPString())); m_pfiReceiveBuffer.Encrypt(); } m_pfiReceiveBuffer.Seek(0); switch (m_NegotiatingState) { case ONS_NONE: // would be a bug wxFAIL; return 0; case ONS_BASIC_CLIENTA_RANDOMPART: { //printf("We are on ONS_BASIC_CLIENTA_RANDOMPART, create the keys on %s\n", (const char*) unicode2char(DbgGetIPString())); // This creates the send/receive keys. uint8_t achKeyData[21]; md4cpy(achKeyData, thePrefs::GetUserHash().GetHash()); m_pfiReceiveBuffer.Read(achKeyData + 17, 4); achKeyData[16] = MAGICVALUE_REQUESTER; //DumpMem(achKeyData, sizeof(achKeyData), wxT("ach:")); MD5Sum md5(achKeyData, sizeof(achKeyData)); //DumpMem(md5.GetRawHash(), 16, wxT("Md5:")); m_pfiReceiveBuffer.SetKey(md5); achKeyData[16] = MAGICVALUE_SERVER; md5.Calculate(achKeyData, sizeof(achKeyData)); m_pfiSendBuffer.SetKey(md5); m_NegotiatingState = ONS_BASIC_CLIENTA_MAGICVALUE; m_nReceiveBytesWanted = 4; break; } case ONS_BASIC_CLIENTA_MAGICVALUE: { // Check the magic value to confirm encryption works. //printf("Creating magic value on negotiate on %s\n", (const char*) unicode2char(DbgGetIPString())); uint32_t dwValue = m_pfiReceiveBuffer.ReadUInt32(); if (dwValue == MAGICVALUE_SYNC) { // yup, the one or the other way it worked, this is an encrypted stream //DEBUG_ONLY( DebugLog(_T("Received proper magic value, clientIP: %s"), DbgGetIPString()) ); // set the receiver key //printf("Magic value works on %s\n", (const char*) unicode2char(DbgGetIPString())); m_NegotiatingState = ONS_BASIC_CLIENTA_METHODTAGSPADLEN; m_nReceiveBytesWanted = 3; } else { //printf("Wrong magic value: 0x%x != 0x%x on %s\n",dwValue, MAGICVALUE_SYNC, (const char*)unicode2char(DbgGetIPString())); //DebugLogError(_T("CEncryptedStreamSocket: Received wrong magic value from clientIP %s on a supposly encrytped stream / Wrong Header"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return (-1); } break; } case ONS_BASIC_CLIENTA_METHODTAGSPADLEN: { // Get encryption method and padding. // Might fall back to padding process, but the bytes will be ignored. //printf("Getting encryption method on negotiation\n"); m_dbgbyEncryptionSupported = m_pfiReceiveBuffer.ReadUInt8(); m_dbgbyEncryptionRequested = m_pfiReceiveBuffer.ReadUInt8(); if (m_dbgbyEncryptionRequested != ENM_OBFUSCATION) { //printf("Unsupported encryption method!\n"); // AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Client %s preffered unsupported encryption method (%i)"), DbgGetIPString(), m_dbgbyEncryptionRequested); } m_nReceiveBytesWanted = m_pfiReceiveBuffer.ReadUInt8(); m_NegotiatingState = ONS_BASIC_CLIENTA_PADDING; if (m_nReceiveBytesWanted > 0) { // No padding break; } } case ONS_BASIC_CLIENTA_PADDING: { //printf("Negotiating on padding, completing\n"); // ignore the random bytes, send the response, set status complete CMemFile fileResponse(26); fileResponse.WriteUInt32(MAGICVALUE_SYNC); const uint8_t bySelectedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version, so no need to look which the other client preferred fileResponse.WriteUInt8(bySelectedEncryptionMethod); amuleIPV4Address address; GetPeer(address); const uint8_t byPaddingLen = theApp->serverconnect->AwaitingTestFromIP(StringIPtoUint32(address.IPAddress())) ? 16 : (thePrefs::GetCryptTCPPaddingLength() + 1); uint8_t byPadding = (uint8_t)(GetRandomUint8() % byPaddingLen); fileResponse.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) { fileResponse.WriteUInt8((uint8_t)rand()); } SendNegotiatingData(fileResponse.GetRawBuffer(), (uint32_t)fileResponse.GetLength()); m_NegotiatingState = ONS_COMPLETE; m_StreamCryptState = ECS_ENCRYPTING; //DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (incoming)"), DbgGetIPString()) ); break; } case ONS_BASIC_CLIENTB_MAGICVALUE: { //printf("Negotiating on magic value\n"); if (m_pfiReceiveBuffer.ReadUInt32() != MAGICVALUE_SYNC) { //DebugLogError(_T("CEncryptedStreamSocket: EncryptedstreamSyncError: Client sent wrong Magic Value as answer, cannot complete handshake (%s)"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return (-1); } m_NegotiatingState = ONS_BASIC_CLIENTB_METHODTAGSPADLEN; m_nReceiveBytesWanted = 2; break; } case ONS_BASIC_CLIENTB_METHODTAGSPADLEN: { //printf("Negotiating on client B pad length\n"); m_dbgbyEncryptionMethodSet = m_pfiReceiveBuffer.ReadUInt8(); if (m_dbgbyEncryptionMethodSet != ENM_OBFUSCATION) { //DebugLogError( _T("CEncryptedStreamSocket: Client %s set unsupported encryption method (%i), handshake failed"), DbgGetIPString(), m_dbgbyEncryptionMethodSet); OnError(ERR_ENCRYPTION); return (-1); } m_nReceiveBytesWanted = m_pfiReceiveBuffer.ReadUInt8(); m_NegotiatingState = ONS_BASIC_CLIENTB_PADDING; if (m_nReceiveBytesWanted > 0) { break; } } case ONS_BASIC_CLIENTB_PADDING: //printf("Negotiating on client B padding, handshake complete\n"); // ignore the random bytes, the handshake is complete m_NegotiatingState = ONS_COMPLETE; m_StreamCryptState = ECS_ENCRYPTING; //DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (outgoing)"), DbgGetIPString()) ); break; case ONS_BASIC_SERVER_DHANSWER: { wxASSERT( !m_cryptDHA.IsZero() ); uint8_t aBuffer[PRIMESIZE_BYTES + 1]; m_pfiReceiveBuffer.Read(aBuffer, PRIMESIZE_BYTES); CryptoPP::Integer cryptDHAnswer((byte*)aBuffer, PRIMESIZE_BYTES); CryptoPP::Integer cryptDHPrime((byte*)dh768_p, PRIMESIZE_BYTES); // our fixed prime CryptoPP::Integer cryptResult = a_exp_b_mod_c(cryptDHAnswer, m_cryptDHA, cryptDHPrime); m_cryptDHA = 0; //DEBUG_ONLY( ZeroMemory(aBuffer, sizeof(aBuffer)) ); wxASSERT( cryptResult.MinEncodedSize() <= PRIMESIZE_BYTES ); // create the keys cryptResult.Encode(aBuffer, PRIMESIZE_BYTES); aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_REQUESTER; MD5Sum md5(aBuffer, sizeof(aBuffer)); m_pfiSendBuffer.SetKey(md5); aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_SERVER; md5.Calculate(aBuffer, sizeof(aBuffer)); m_pfiReceiveBuffer.SetKey(md5); m_NegotiatingState = ONS_BASIC_SERVER_MAGICVALUE; m_nReceiveBytesWanted = 4; break; } case ONS_BASIC_SERVER_MAGICVALUE: { uint32_t dwValue = m_pfiReceiveBuffer.ReadUInt32(); if (dwValue == MAGICVALUE_SYNC) { // yup, the one or the other way it worked, this is an encrypted stream //DebugLog(_T("Received proper magic value after DH-Agreement from Serverconnection IP: %s"), DbgGetIPString()); // set the receiver key m_NegotiatingState = ONS_BASIC_SERVER_METHODTAGSPADLEN; m_nReceiveBytesWanted = 3; } else { //DebugLogError(_T("CEncryptedStreamSocket: Received wrong magic value after DH-Agreement from Serverconnection"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return (-1); } break; } case ONS_BASIC_SERVER_METHODTAGSPADLEN: m_dbgbyEncryptionSupported = m_pfiReceiveBuffer.ReadUInt8(); m_dbgbyEncryptionRequested = m_pfiReceiveBuffer.ReadUInt8(); if (m_dbgbyEncryptionRequested != ENM_OBFUSCATION) { // AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Server %s preffered unsupported encryption method (%i)"), DbgGetIPString(), m_dbgbyEncryptionRequested); } m_nReceiveBytesWanted = m_pfiReceiveBuffer.ReadUInt8(); m_NegotiatingState = ONS_BASIC_SERVER_PADDING; if (m_nReceiveBytesWanted > 0) { break; } case ONS_BASIC_SERVER_PADDING: { // ignore the random bytes (they are decrypted already), send the response, set status complete CMemFile fileResponse(26); fileResponse.WriteUInt32(MAGICVALUE_SYNC); const uint8_t bySelectedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version, so no need to look which the other client preferred fileResponse.WriteUInt8(bySelectedEncryptionMethod); // Server callback connection only allows 16 bytes of padding. uint8_t byPadding = (uint8_t)(GetRandomUint8() % 16); fileResponse.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) { fileResponse.WriteUInt8((uint8_t)rand()); } m_NegotiatingState = ONS_BASIC_SERVER_DELAYEDSENDING; SendNegotiatingData(fileResponse.GetRawBuffer(), (uint32_t)fileResponse.GetLength(), 0, true); // don't actually send it right now, store it in our sendbuffer m_StreamCryptState = ECS_ENCRYPTING; //DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished DH Obufscation handshake with Server %s"), DbgGetIPString()) ); break; } default: wxFAIL; } m_pfiReceiveBuffer.ResetData(); } return nRead; } catch(...) { // can only be caused by a bug in negationhandling, not by the datastream //error->Delete(); //printf("Bug on negotiation?\n"); wxFAIL; OnError(ERR_ENCRYPTION); m_pfiReceiveBuffer.ResetData(); return (-1); } }
void CBackProp::recalWeight(SOCKET conn) { // server // share the dwt // re apply AutoSeededRandomPool rnd; unsigned int bits = 512; DH dh; dh.AccessGroupParameters().GenerateRandomWithKeySize(rnd, bits); if(!dh.GetGroupParameters().ValidateGroup(rnd, 3)) throw runtime_error("Failed to validate prime and generator"); size_t count = 0; const Integer& p = dh.GetGroupParameters().GetModulus(); const Integer& q = dh.GetGroupParameters().GetSubgroupOrder(); Send(conn, p); Send(conn, q); CryptoPP::Integer g = RandomQuadraticResidue(p); Send(conn, g); CryptoPP::Integer ua = RandomQuadraticResidue(q); ModularArithmetic group_S(p); CryptoPP::Integer VA = group_S.Exponentiate(g, ua); // receive VB from Party B. byte output[128]; unsigned char buf[8]; CryptoPP::Integer VB; recv(conn,(char *)output, 128,0); VB.Decode(output, 128); CryptoPP::Integer rA1 = RandomQuadraticResidue(q); CryptoPP::Integer rA2 = RandomQuadraticResidue(q); for(int i=1;i<numl;i++) for(int j=0;j<lsize[i];j++) for(int k=0;k<lsize[i-1]+1;k++) { //Party A XA = dwt[i][j][k] YA = 10000.0 CryptoPP::Integer XA, YA; //dwt[i][j][k] = -1505; XA = (int)(dwt[i][j][k] / 2); YA = 1000 / 2; // divided by 10 //Send g and p, q to B CryptoPP::Integer xA1 = group_S.Exponentiate(g, rA1); CryptoPP::Integer xA2; if( XA >= 0) xA2 = (group_S.Exponentiate((VA * VB), rA1) * group_S.Exponentiate(g, XA)); else xA2 = group_S.Divide(group_S.Exponentiate((VA * VB), rA1) , group_S.Exponentiate(g, -XA)); CryptoPP::Integer yA1 = group_S.Exponentiate(g, rA2); CryptoPP::Integer yA2; if( YA >= 0) yA2 = (group_S.Exponentiate((VA * VB), rA2) * group_S.Exponentiate(g, YA)); else yA2 = group_S.Divide(group_S.Exponentiate((VA * VB), rA2), group_S.Exponentiate(g, -YA)); Send(conn, xA1); Send(conn, xA2); Send(conn, yA1); Send(conn, yA2); CryptoPP::Integer theta1, theta2, pi1, pi2; recv(conn,(char *)output, 128,0); theta1.Decode(output, 128); recv(conn,(char *)output, 128,0); theta2.Decode(output, 128); recv(conn,(char *)output, 128,0); pi1.Decode(output, 128); recv(conn,(char *)output, 128,0); pi2.Decode(output, 128); // compute eta CryptoPP::Integer eta1 = group_S.Divide(theta1 , group_S.Exponentiate(pi1, ua)); CryptoPP::Integer eta2 = group_S.Divide(theta2 , group_S.Exponentiate(pi2, ua)); Send(conn, eta1); Send(conn, eta2); //TODO: Receive the average result int peta1, peta2; recv(conn, (char *)buf, 4, 0); peta1 = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + (buf[3] << 0); //cout << "peta1 " << peta1 << endl; recv(conn,(char *)buf, 4,0); peta2 = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + (buf[3] << 0); //cout << "peta2 " << peta2 << endl; double avgWeight = (double)peta1 / ((double)peta2 * 10.0 ); weight[i][j][k] = prevWeight[i][j][k] + avgWeight; } }
void Send(SOCKET s, CryptoPP::Integer item){ byte output[128]; item.Encode(output, 128); send(s, (char *)output, 128, 0); }
///////////////////////////////////////////////////////////////////////////// // Deterministically generate new private key using a chaincode // Changed: added using the hash of the public key to the mix // b/c multiplying by the chaincode alone is too "linear" // (there's no reason to believe it's insecure, but it doesn't // hurt to add some extra entropy/non-linearity to the chain // generation process) SecureBinaryData CryptoECDSA::ComputeChainedPrivateKey( SecureBinaryData const & binPrivKey, SecureBinaryData const & chainCode, SecureBinaryData binPubKey, SecureBinaryData* multiplierOut) { if(CRYPTO_DEBUG) { cout << "ComputeChainedPrivateKey:" << endl; cout << " BinPrv: " << binPrivKey.toHexStr() << endl; cout << " BinChn: " << chainCode.toHexStr() << endl; cout << " BinPub: " << binPubKey.toHexStr() << endl; } if( binPubKey.getSize()==0 ) binPubKey = ComputePublicKey(binPrivKey); if( binPrivKey.getSize() != 32 || chainCode.getSize() != 32) { LOGERR << "***ERROR: Invalid private key or chaincode (both must be 32B)"; LOGERR << "BinPrivKey: " << binPrivKey.getSize(); LOGERR << "BinPrivKey: (not logged for security)"; //LOGERR << "BinPrivKey: " << binPrivKey.toHexStr(); LOGERR << "BinChain : " << chainCode.getSize(); LOGERR << "BinChain : " << chainCode.toHexStr(); } // Adding extra entropy to chaincode by xor'ing with hash256 of pubkey BinaryData chainMod = binPubKey.getHash256(); BinaryData chainOrig = chainCode.getRawCopy(); BinaryData chainXor(32); for(uint8_t i=0; i<8; i++) { uint8_t offset = 4*i; *(uint32_t*)(chainXor.getPtr()+offset) = *(uint32_t*)( chainMod.getPtr()+offset) ^ *(uint32_t*)(chainOrig.getPtr()+offset); } // Hard-code the order of the group static SecureBinaryData SECP256K1_ORDER_BE = SecureBinaryData().CreateFromHex( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); CryptoPP::Integer mult, origPrivExp, ecOrder; // A mult.Decode(chainXor.getPtr(), chainXor.getSize(), UNSIGNED); // B origPrivExp.Decode(binPrivKey.getPtr(), binPrivKey.getSize(), UNSIGNED); // C ecOrder.Decode(SECP256K1_ORDER_BE.getPtr(), SECP256K1_ORDER_BE.getSize(), UNSIGNED); // A*B mod C will get us a new private key exponent CryptoPP::Integer newPrivExponent = a_times_b_mod_c(mult, origPrivExp, ecOrder); // Convert new private exponent to big-endian binary string SecureBinaryData newPrivData(32); newPrivExponent.Encode(newPrivData.getPtr(), newPrivData.getSize(), UNSIGNED); if(multiplierOut != NULL) (*multiplierOut) = SecureBinaryData(chainXor); //LOGINFO << "Computed new chained private key using:"; //LOGINFO << " Public key: " << binPubKey.toHexStr().c_str(); //LOGINFO << " PubKeyHash: " << chainMod.toHexStr().c_str(); //LOGINFO << " Chaincode: " << chainOrig.toHexStr().c_str(); //LOGINFO << " Multiplier: " << chainXor.toHexStr().c_str(); return newPrivData; }