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; }