-
-
[原创]C++ECIES随便一甩。
-
发表于: 2017-9-14 01:07 4783
-
/** * Author: DengTao * Created: 2017.08.07 * * (c) Copyright by DengTao. **/ #include "ecies/bignum_key.h" #include <openssl/err.h> #include <openssl/ec.h> #include <openssl/evp.h> #include <openssl/pem.h> #include <openssl/rand.h> #include <openssl/bio.h> #include <openssl/bn.h> #include <openssl/hmac.h> namespace FinSky{ EC_POINT *EC_POINT_mult_BN(const EC_GROUP *group, EC_POINT *P, const EC_POINT *a, const BIGNUM *b, BN_CTX *ctx) { EC_POINT *O = EC_POINT_new(group); if (P == NULL) P = EC_POINT_new(group); for (int i = BN_num_bits(b); i >= 0; i--) { EC_POINT_dbl(group, P, P, ctx); if (BN_is_bit_set(b, i)) EC_POINT_add(group, P, P, a, ctx); else EC_POINT_add(group, P, P, O, ctx); } return P; } BigNumKey::BigNumKey() : public_handle_s_(0), public_handle_r_(0), private_handle_s_(0), private_handle_r_(0), ec_key_handle_(0){ public_s_.resize(0); public_r_.resize(0); private_s_.resize(0); private_r_.resize(0); } BigNumKey::~BigNumKey(){ public_s_.resize(0); public_r_.resize(0); private_s_.resize(0); private_r_.resize(0); BN_free(reinterpret_cast<BIGNUM*>(public_handle_r_.get())); BN_free(reinterpret_cast<BIGNUM*>(public_handle_s_.get())); BN_free(reinterpret_cast<BIGNUM*>(private_handle_r_.get())); BN_free(reinterpret_cast<BIGNUM*>(private_handle_s_.get())); } bool BigNumKey::SetECKey(const std::string& private_key){ BIO *b = BIO_new_mem_buf((void*)private_key.c_str(), private_key.size()); EVP_PKEY *pkey = NULL; if (private_key.find("PRIVATE") != std::string::npos) PEM_read_bio_PrivateKey(b, &pkey, NULL, NULL); else PEM_read_bio_PUBKEY(b, &pkey, NULL, NULL); ec_key_handle_ = (BigNumKeyHandle)EVP_PKEY_get1_EC_KEY(pkey); BIO_free(b); EVP_PKEY_free(pkey); return true; } bool BigNumKey::ECKeyPublicDeriveRS(){ ////////////////////////////////////////////////////////////////////////// public_handle_r_ = (BigNumKeyHandle)BN_new(); public_handle_s_ = (BigNumKeyHandle)BN_new(); BN_CTX *ctx = BN_CTX_new(); const EC_GROUP *group = EC_KEY_get0_group(reinterpret_cast<EC_KEY*>(ec_key_handle_.get())); const EC_POINT *Kb = EC_KEY_get0_public_key(reinterpret_cast<EC_KEY*>(ec_key_handle_.get())); BIGNUM *n = BN_new(); BIGNUM *r = BN_new(); EC_POINT *P = NULL; EC_POINT *Rp = EC_POINT_new(group); BIGNUM *Py = BN_new(); const EC_POINT *G = EC_GROUP_get0_generator(group); int bits, ret = -1; EC_GROUP_get_order(group, n, ctx); bits = BN_num_bits(n); BN_rand(r, bits, -1, 0); /* calculate R = rG */ Rp = EC_POINT_mult_BN(group, Rp, G, r, ctx); /* calculate S = Px, P = (Px,Py) = Kb R */ P = EC_POINT_mult_BN(group, P, Kb, r, ctx); if (!EC_POINT_is_at_infinity(group, P)) { EC_POINT_get_affine_coordinates_GF2m(group, P, reinterpret_cast<BIGNUM*>(public_handle_s_.get()), Py, ctx); EC_POINT_point2bn(group, Rp, POINT_CONVERSION_COMPRESSED, reinterpret_cast<BIGNUM*>(public_handle_r_.get()), ctx); ret = 0; } BN_free(r); BN_free(n); BN_free(Py); EC_POINT_free(P); EC_POINT_free(Rp); BN_CTX_free(ctx); return (ret!=0); } bool BigNumKey::ECKeyPrivateDeriveRS(){ //ReversePublicR(); private_handle_r_ = (BigNumKeyHandle)BN_bin2bn(&public_r_[0], public_r_.size(), BN_new()); private_handle_s_ = (BigNumKeyHandle)BN_new(); int ret = -1; BN_CTX *ctx = BN_CTX_new(); BIGNUM *n = BN_new(); BIGNUM *Py = BN_new(); const EC_GROUP *group = EC_KEY_get0_group(reinterpret_cast<EC_KEY*>(ec_key_handle_.get())); EC_POINT *Rp = EC_POINT_bn2point(group, reinterpret_cast<BIGNUM*>(private_handle_r_.get()), NULL, ctx); const BIGNUM *kB = EC_KEY_get0_private_key(reinterpret_cast<EC_KEY*>(ec_key_handle_.get())); EC_GROUP_get_order(group, n, ctx); /* Calculate S = Px, P = (Px, Py) = R kB */ EC_POINT *P = EC_POINT_mult_BN(group, NULL, Rp, kB, ctx); if (!EC_POINT_is_at_infinity(group, P)) { EC_POINT_get_affine_coordinates_GF2m(group, P, reinterpret_cast<BIGNUM*>(private_handle_s_.get()), Py, ctx); ret = 0; } BN_free(n); BN_free(Py); EC_POINT_free(Rp); EC_POINT_free(P); BN_CTX_free(ctx); return (ret!=0); } void BigNumKey::PublicR(){ public_r_.resize(BN_num_bytes(reinterpret_cast<BIGNUM*>(public_handle_r_.get()))); BN_bn2bin(reinterpret_cast<const BIGNUM*>(public_handle_r_.get()), &public_r_[0]); } void BigNumKey::PublicS(){ public_s_.resize(BN_num_bytes(reinterpret_cast<BIGNUM*>(public_handle_s_.get()))); BN_bn2bin(reinterpret_cast<const BIGNUM*>(public_handle_s_.get()), &public_s_[0]); } void BigNumKey::PrivateR(){ private_r_.resize(BN_num_bytes(reinterpret_cast<BIGNUM*>(private_handle_r_.get()))); BN_bn2bin(reinterpret_cast<BIGNUM*>(private_handle_r_.get()), &private_r_[0]); } void BigNumKey::PrivateS(){ private_s_.resize(BN_num_bytes(reinterpret_cast<BIGNUM*>(private_handle_s_.get()))); BN_bn2bin(reinterpret_cast<BIGNUM*>(private_handle_s_.get()), &private_s_[0]); } void BigNumKey::ReversePublicR(){ public_r_.resize(BN_num_bytes(reinterpret_cast<BIGNUM*>(public_handle_r_.get()))); BN_bn2bin(reinterpret_cast<BIGNUM*>(public_handle_r_.get()), &public_r_[0]); } }
/** * Author: DengTao * Created: 2017.08.07 * * (c) Copyright by DengTao. **/ #include "ecies/decrypt_message.h" #include <openssl/err.h> #include <openssl/ec.h> #include <openssl/evp.h> #include <openssl/pem.h> #include <openssl/rand.h> #include <openssl/bio.h> #include <openssl/bn.h> #include <openssl/hmac.h> namespace FinSky{ DecryptMessage::DecryptMessage(const std::string& private_key){ key_.SetECKey(private_key); salt_.resize(0); checksum_.resize(0); } DecryptMessage::~DecryptMessage(){ salt_.resize(0); checksum_.resize(0); } bool DecryptMessage::DecryptBytes(const std::vector<std::uint8_t>& bytes){ key_.ECKeyPrivateDeriveRS(); key_.PrivateS(); std::vector<std::uint8_t> private_s = key_.private_s(); const EVP_MD *md = EVP_sha1(); const EVP_CIPHER *cipher = EVP_aes_256_cbc(); size_t ke_len = EVP_CIPHER_key_length(cipher) + EVP_CIPHER_iv_length(cipher); size_t km_len = EVP_MD_block_size(md); unsigned char *ke_km = new unsigned char[ke_len + km_len]; memset(ke_km, 0, ke_len + km_len); unsigned char *dc_out = new unsigned char[bytes.size() * 5]; assert(ke_km != nullptr&&dc_out != nullptr); memset(dc_out, 0, bytes.size() * 5); size_t dc_len = 0; int outl = 0; PKCS5_PBKDF2_HMAC((const char*)&private_s[0], private_s.size(), &salt_[0], salt_.size(), kHMACIter, md, ke_len + km_len, ke_km); unsigned char *dv_out = new unsigned char[km_len]; assert(dv_out != nullptr); unsigned int dv_len; HMAC(md, ke_km + ke_len, km_len, &bytes[0], bytes.size(), dv_out, &dv_len); if (checksum_.size() != dv_len || memcmp(dv_out, &checksum_[0], dv_len) != 0){ printf("MAC verification failed\n"); return true; } EVP_CIPHER_CTX *ectx = EVP_CIPHER_CTX_new(); EVP_DecryptInit_ex(ectx, cipher, NULL, ke_km, ke_km + EVP_CIPHER_key_length(cipher)); EVP_DecryptUpdate(ectx, dc_out + dc_len, &outl, &bytes[0], bytes.size()); dc_len += outl; EVP_DecryptFinal_ex(ectx, dc_out + dc_len, &outl); dc_len += outl; dc_out[dc_len] = 0; clear_text_.resize(dc_len); memmove(&clear_text_[0], dc_out, dc_len); delete[] dc_out; delete[] ke_km; delete[] dv_out; return 0; } void DecryptMessage::SetPublicR(const std::vector<std::uint8_t>& s3){ key_.SetPublicR(s3); } }
/** * Author: DengTao * Created: 2017.08.07 * * (c) Copyright by DengTao. **/ #include "ecies/encrypt_message.h" #include <openssl/err.h> #include <openssl/ec.h> #include <openssl/evp.h> #include <openssl/pem.h> #include <openssl/rand.h> #include <openssl/bio.h> #include <openssl/bn.h> #include <openssl/hmac.h> namespace FinSky{ EncryptMessage::EncryptMessage(const std::string& private_key){ key_.SetECKey(private_key); salt_.resize(32); checksum_.resize(0); cipher_text_.resize(0); RAND_bytes(&salt_[0], salt_.size()); } EncryptMessage::~EncryptMessage(){ salt_.resize(0); checksum_.resize(0); cipher_text_.resize(0); } bool EncryptMessage::EncryptString(const std::string& str){ std::vector<std::uint8_t> v; std::copy(str.begin(), str.end(), std::back_inserter(v)); return EncryptBytes(v); } bool EncryptMessage::EncryptBytes(const std::vector<std::uint8_t>& bytes){ unsigned char *c_out = new unsigned char[bytes.size() * 5]; size_t c_len; unsigned char *d_out = new unsigned char[bytes.size() * 5]; size_t d_len; assert(c_out != nullptr&&d_out != nullptr); memset(c_out, 0, bytes.size() * 5); memset(d_out, 0, bytes.size() * 5); const std::vector<std::uint8_t> loc_salt = salt(); key_.ECKeyPublicDeriveRS(); key_.PublicS(); std::vector<std::uint8_t> public_s = key_.public_s(); const EVP_MD *md = EVP_sha1(); const EVP_CIPHER *cipher = EVP_aes_256_cbc(); size_t ke_len = EVP_CIPHER_key_length(cipher) + EVP_CIPHER_iv_length(cipher); size_t km_len = EVP_MD_block_size(md); unsigned char *ke_km = new unsigned char[ke_len + km_len]; assert(ke_km != nullptr); memset(ke_km, 0, ke_len + km_len); c_len = 0; int outl = 0; PKCS5_PBKDF2_HMAC((const char*)(const char*)&public_s[0], public_s.size(), &loc_salt[0], loc_salt.size(), kHMACIter, md, ke_len + km_len, ke_km); EVP_CIPHER_CTX *ectx = EVP_CIPHER_CTX_new(); EVP_EncryptInit_ex(ectx, cipher, NULL, ke_km, ke_km + EVP_CIPHER_key_length(cipher)); EVP_EncryptUpdate(ectx, c_out + c_len, &outl, (const unsigned char*)&bytes[0], bytes.size()); c_len += outl; EVP_EncryptFinal_ex(ectx, c_out + c_len, &outl); c_len += outl; unsigned int len; HMAC(md, ke_km + ke_len, km_len, c_out, c_len, d_out, &len); d_len = len; checksum_.resize(d_len); cipher_text_.resize(c_len); memmove(&cipher_text_[0], c_out, c_len); memmove(&checksum_[0], d_out, d_len); key_.ReversePublicR(); public_r_ = key_.public_r(); delete[] c_out; delete[] d_out; delete[] ke_km; return false; } }
// openssl_ecies.cpp : Defines the entry point for the console application. // #include "stdafx.h" #define _CRTDBG_MAP_ALLOC #include<stdlib.h> #include<crtdbg.h> #pragma comment(lib,"libcrypto.lib") #pragma comment(lib,"libssl.lib") #include <openssl/err.h> #include <openssl/ec.h> #include <openssl/evp.h> #include <openssl/pem.h> #include <openssl/rand.h> #include <openssl/bio.h> #include <openssl/bn.h> #include <openssl/hmac.h> #include "BigNumKey.h" #include "EncryptMessage.h" #include "DecryptMessage.h" const char pkey[] = "-----BEGIN PUBLIC KEY-----\n" \ "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgv/5+wE/2gT5ANCpZ9kIy3nKgcqH\n" \ "YDyNC/d0bgf9Pdaus40CXjIZukF1uUAWAo4GTqG7uDatXWOzq1MIDgE6bA==\n" \ "-----END PUBLIC KEY-----\n"; const char privkey[] = "-----BEGIN EC PRIVATE KEY-----\n" \ "MHcCAQEEILmUAvLj7GGSykQxpHeems8Yjw03V7ACBmD8udiNm92soAoGCCqGSM49\n" \ "AwEHoUQDQgAEgv/5+wE/2gT5ANCpZ9kIy3nKgcqHYDyNC/d0bgf9Pdaus40CXjIZ\n" \ "ukF1uUAWAo4GTqG7uDatXWOzq1MIDgE6bA==\n" \ "-----END EC PRIVATE KEY-----\n"; int _tmain(int argc, _TCHAR* argv[]) { _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); //https://github.com/cmouse/ecies/blob/master/ecies.c //openssl ecparam -genkey -name prime256v1 -noout -out ecprivkey.pem //openssl ec -in ecprivkey.pem -pubout -out ecpubkey.pem OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); const std::string msg = "super secret message"; const std::string public_key = pkey; ECIES::EncryptMessage encrypt_message(public_key); encrypt_message.EncryptString(msg); std::vector<std::uint8_t> salt = encrypt_message.salt(); std::vector<std::uint8_t> checksum = encrypt_message.checksum(); std::vector<std::uint8_t> ciphertext = encrypt_message.cipher_text(); const std::string private_key = privkey; ECIES::DecryptMessage decrypt_message(private_key); decrypt_message.SetSalt(salt); decrypt_message.SetChecksum(checksum); decrypt_message.SetPublicR(encrypt_message.public_r()); decrypt_message.DecryptBytes(ciphertext); return 0; }
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
他的文章
谁下载
看原图
赞赏
雪币:
留言: