bytes Secp256k1PP::eciesKDF(Secret const& _z, bytes _s1, unsigned kdByteLen) { auto reps = ((kdByteLen + 7) * 8) / (CryptoPP::SHA256::BLOCKSIZE * 8); // SEC/ISO/Shoup specify counter size SHOULD be equivalent // to size of hash output, however, it also notes that // the 4 bytes is okay. NIST specifies 4 bytes. bytes ctr({0, 0, 0, 1}); bytes k; CryptoPP::SHA256 ctx; for (unsigned i = 0; i <= reps; i++) { ctx.Update(ctr.data(), ctr.size()); ctx.Update(_z.data(), Secret::size); ctx.Update(_s1.data(), _s1.size()); // append hash to k bytes digest(32); ctx.Final(digest.data()); ctx.Restart(); k.reserve(k.size() + h256::size); move(digest.begin(), digest.end(), back_inserter(k)); if (++ctr[3] || ++ctr[2] || ++ctr[1] || ++ctr[0]) continue; } k.resize(kdByteLen); return k; }
void Secp256k1PP::encryptECIES(Public const& _k, bytesConstRef _sharedMacData, bytes& io_cipher) { // interop w/go ecies implementation auto r = KeyPair::create(); Secret z; ecdh::agree(r.sec(), _k, z); auto key = eciesKDF(z, bytes(), 32); bytesConstRef eKey = bytesConstRef(&key).cropped(0, 16); bytesRef mKeyMaterial = bytesRef(&key).cropped(16, 16); CryptoPP::SHA256 ctx; ctx.Update(mKeyMaterial.data(), mKeyMaterial.size()); bytes mKey(32); ctx.Final(mKey.data()); bytes cipherText = encryptSymNoAuth(SecureFixedHash<16>(eKey), h128(), bytesConstRef(&io_cipher)); if (cipherText.empty()) return; bytes msg(1 + Public::size + h128::size + cipherText.size() + 32); msg[0] = 0x04; r.pub().ref().copyTo(bytesRef(&msg).cropped(1, Public::size)); bytesRef msgCipherRef = bytesRef(&msg).cropped(1 + Public::size + h128::size, cipherText.size()); bytesConstRef(&cipherText).copyTo(msgCipherRef); // tag message CryptoPP::HMAC<SHA256> hmacctx(mKey.data(), mKey.size()); bytesConstRef cipherWithIV = bytesRef(&msg).cropped(1 + Public::size, h128::size + cipherText.size()); hmacctx.Update(cipherWithIV.data(), cipherWithIV.size()); hmacctx.Update(_sharedMacData.data(), _sharedMacData.size()); hmacctx.Final(msg.data() + 1 + Public::size + cipherWithIV.size()); io_cipher.resize(msg.size()); io_cipher.swap(msg); }
void CEncrypt::CreateUserKey() { CryptoPP::RandomPool prng; CryptoPP::SecByteBlock salt(16); CryptoPP::OS_GenerateRandomBlock(false, salt, salt.size()); prng.IncorporateEntropy(salt, salt.size()); memcpy(m_anUserKey + 32, salt.data(), salt.size()); CryptoPP::SHA256 hash; hash.Update( (unsigned char*) impl->m_sUserPassword.c_str(), impl->m_sUserPassword.length()); hash.Update( m_anUserKey + 32, 8); CryptoPP::SecByteBlock pHashData(hash.DigestSize()); hash.Final(pHashData); if (MakeFileKey3(impl->m_sUserPassword, pHashData.data(), pHashData.size())) { memcpy(m_anUserKey, pHashData.data(), pHashData.size()); hash.Update( (unsigned char*) impl->m_sUserPassword.c_str(), impl->m_sUserPassword.length()); hash.Update( m_anUserKey + 40, 8); CryptoPP::SecByteBlock pHashKeyData(hash.DigestSize()); hash.Final(pHashKeyData); MakeFileKey3(impl->m_sUserPassword, pHashKeyData.data(), pHashKeyData.size()); unsigned char empty[16] = {}; CryptoPP::AES::Encryption aesEncryption(pHashKeyData.data(), pHashKeyData.size()); CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption( aesEncryption, empty); CryptoPP::StreamTransformationFilter stfEncryption(cbcEncryption, new CryptoPP::ArraySink( m_anUserEncryptKey, 32), CryptoPP::StreamTransformationFilter::NO_PADDING ); stfEncryption.Put2(impl->m_anEncryptionKey, 32, 1, true); stfEncryption.MessageEnd(); } }
bool Secp256k1PP::decryptECIES(Secret const& _k, bytesConstRef _sharedMacData, bytes& io_text) { // interop w/go ecies implementation // io_cipher[0] must be 2, 3, or 4, else invalidpublickey if (io_text.empty() || io_text[0] < 2 || io_text[0] > 4) // invalid message: publickey return false; if (io_text.size() < (1 + Public::size + h128::size + 1 + h256::size)) // invalid message: length return false; Secret z; if (!ecdh::agree(_k, *(Public*)(io_text.data() + 1), z)) return false; // Invalid pubkey or seckey. auto key = ecies::kdf(z, bytes(), 64); bytesConstRef eKey = bytesConstRef(&key).cropped(0, 16); bytesRef mKeyMaterial = bytesRef(&key).cropped(16, 16); bytes mKey(32); CryptoPP::SHA256 ctx; ctx.Update(mKeyMaterial.data(), mKeyMaterial.size()); ctx.Final(mKey.data()); bytes plain; size_t cipherLen = io_text.size() - 1 - Public::size - h128::size - h256::size; bytesConstRef cipherWithIV(io_text.data() + 1 + Public::size, h128::size + cipherLen); bytesConstRef cipherIV = cipherWithIV.cropped(0, h128::size); bytesConstRef cipherNoIV = cipherWithIV.cropped(h128::size, cipherLen); bytesConstRef msgMac(cipherNoIV.data() + cipherLen, h256::size); h128 iv(cipherIV.toBytes()); // verify tag CryptoPP::HMAC<CryptoPP::SHA256> hmacctx(mKey.data(), mKey.size()); hmacctx.Update(cipherWithIV.data(), cipherWithIV.size()); hmacctx.Update(_sharedMacData.data(), _sharedMacData.size()); h256 mac; hmacctx.Final(mac.data()); for (unsigned i = 0; i < h256::size; i++) if (mac[i] != msgMac[i]) return false; plain = decryptSymNoAuth(SecureFixedHash<16>(eKey), iv, cipherNoIV).makeInsecure(); io_text.resize(plain.size()); io_text.swap(plain); return true; }
bool CCryptoModulus::InitCrypto(BYTE *temp, DWORD length) { int hashid = 0; BYTE digest[2048]; memset(digest, 0, sizeof(digest)); if (length >= 10) { hashid = temp[4] ^ (temp[3] | (temp[1] ^ temp[0]) < temp[2] % 3); } else { hashid = temp[0]; } hashid = (hashid % 11) - 1; switch (hashid) { case 0: { CryptoPP::SHA256 hash; hash.Update(temp, length); hash.Final(digest); this->m_algorithm = digest[0] % 10; this->InitCrypto(this->m_algorithm, digest, 32); } break; case 2: { CryptoPP::SHA512 hash; hash.Update(temp, length); hash.Final(digest); this->m_algorithm = digest[1] % 10; this->InitCrypto(this->m_algorithm, digest, 64); } break; case 3: { CryptoPP::SHA384 hash; hash.Update(temp, length); hash.Final(digest); this->m_algorithm = digest[2] % 10; this->InitCrypto(this->m_algorithm, digest, 48); } break; case 4: { CryptoPP::Weak1::MD4 hash; hash.Update(temp, length); hash.Final(digest); this->m_algorithm = digest[3] % 10; this->InitCrypto(this->m_algorithm, digest, 16); } break; case 5: { CryptoPP::Weak1::MD5 hash; hash.Update(temp, length); hash.Final(digest); this->m_algorithm = digest[4] % 10; this->InitCrypto(this->m_algorithm, digest, 16); } break; case 6: { CryptoPP::RIPEMD160 hash; hash.Update(temp, length); hash.Final(digest); this->m_algorithm = digest[5] % 10; this->InitCrypto(this->m_algorithm, digest, 20); } break; case 7: { CryptoPP::RIPEMD320 hash; hash.Update(temp, length); hash.Final(digest); this->m_algorithm = digest[6] % 10; this->InitCrypto(this->m_algorithm, digest, 40); } break; case 8: { CryptoPP::RIPEMD128 hash; hash.Update(temp, length); hash.Final(digest); this->m_algorithm = digest[7] % 10; this->InitCrypto(this->m_algorithm, digest, 16); } break; case 9: { CryptoPP::RIPEMD256 hash; hash.Update(temp, length); hash.Final(digest); this->m_algorithm = digest[8] % 10; this->InitCrypto(this->m_algorithm, digest, 32); } break; default: { CryptoPP::Weak1::MD5 hash; hash.Update(temp, length); hash.Final(digest); this->m_algorithm = digest[9] % 10; this->InitCrypto(this->m_algorithm, digest, 16); } break; } return true; }