bool PubAddr::loadAddr(ustring address) { unsigned int i = 0; string BM = address.getString(3, i); if (strncmp(BM.c_str(), "BM-", 3) != 0) { i = 0; } char retu[100]; size_t size2 = 50; if (b58tobin(retu, &size2, (char *)address.getRest(i).c_str()) != true) { return false; //ignoring key not valid } ustring _buffer; retu[size2] = 0x00; for (unsigned int j = 0; j < size2; j++) _buffer += retu[j]; i = 0; unsigned int checkPos = _buffer.length() - 4; if (checkPos < (unsigned int)0) return false; ustring buffer = _buffer.getUstring(checkPos, i); byte checksum[4]; memcpy(checksum, _buffer.getUstring(4, checkPos).c_str(), sizeof checksum); CryptoPP::SHA512 hash; byte digest[CryptoPP::SHA512::DIGESTSIZE]; byte digest2[CryptoPP::SHA512::DIGESTSIZE]; hash.CalculateDigest(digest, (byte*)buffer.c_str(), buffer.length()); hash.CalculateDigest(digest2, digest, sizeof digest); if (memcmp(digest2, checksum, sizeof checksum)!=0) { return false; //ignoring key not valid } i = 0; std::unique_lock<std::shared_timed_mutex> mlock(this->mutex_); this->address = address; int tmp_vers = (int)buffer.getVarInt_B(i); int tmp_stream = (int)buffer.getVarInt_B(i); ustring tmp_ripe = buffer.getRest(i); if (tmp_ripe.length() > 20) return false; //too long if (tmp_ripe.length() < 4) return false; //too short this->version = tmp_vers; this->stream = tmp_stream; while (tmp_ripe.length() != 20) //todo add function prepend { ustring tmp2; tmp2.appendInt8(0); tmp2+=tmp_ripe; tmp_ripe = tmp2; } this->ripe.clear(); this->ripe = tmp_ripe; buffer.clear(); buffer.appendVarInt_B(this->version); buffer.appendVarInt_B(this->stream); buffer += this->ripe; hash.CalculateDigest(digest, (byte*)buffer.c_str(), buffer.length()); hash.CalculateDigest(digest2, digest, sizeof digest); this->tagE.clear(); this->tagE.append(digest2, 32); this->tag.clear(); this->tag.append(&(digest2[32]), 32); this->empty = true; mlock.unlock(); return true; }
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; }