#include "RSACrypto.h" #ifdef _WIN32 #include #endif #include #include #include #include #include #include #include #include #include namespace Security { static const char rnd_seed[] = "alsfkdj#$^#Y$JBGVKA()#$J@J#OTJG)(@JG)@GJ)J@$)JG)$JG)GJ#@)G"; class StaticInitializer { public: StaticInitializer() { } ~StaticInitializer() { RAND_cleanup(); } void Init() { RAND_seed( rnd_seed, sizeof( rnd_seed ) ); } }; void InitRandomSeed() { static StaticInitializer s; s.Init(); } // RSA cryptography //RSACrypto::PublicKey::PublicKey(const unsigned char* n, int nsize, const unsigned char* e, int esize) //{ // rsa_ = Alloc(); // BIGNUM* tmp = NULL; // tmp = BN_bin2bn( n, nsize, rsa_->n ); // assert( tmp ); // tmp = BN_bin2bn( e, esize, rsa_->e ); // assert( tmp ); // //#ifdef _DEBUG // // printf("n:"); // // BN_print_fp(stdout, rsa_->n); // // printf(""); // // printf("e:"); // // BN_print_fp(stdout, rsa_->e); // // printf(""); // //#endif //} RSACrypto::PublicKey::PublicKey(const char* n, const char* e) { rsa_ = Alloc(); #if OPENSSL_VERSION_NUMBER < 0x10100000L BN_hex2bn(&rsa_->n, n); BN_hex2bn(&rsa_->e, e); #else BIGNUM* rsa_n, * rsa_e, * rsa_d; RSA_get0_key(rsa_, (const BIGNUM**)&rsa_n, (const BIGNUM**)&rsa_e, (const BIGNUM**)&rsa_d); BN_hex2bn(&rsa_n, n); BN_hex2bn(&rsa_e, e); RSA_set0_key(rsa_, rsa_n, rsa_e, rsa_d); #endif } RSACrypto::PublicKey::PublicKey(RSACrypto::PublicKey& p) { rsa_ = RSA_new(); assert( rsa_ ); Copy( rsa_, p.rsa_ ); } RSACrypto::PublicKey::~PublicKey() { Free( rsa_ ); rsa_ = NULL; } RSACrypto::PublicKey& RSACrypto::PublicKey::operator =(const RSACrypto::PublicKey& p) { if ( rsa_ ) { Free( rsa_ ); rsa_ = NULL; } rsa_ = RSA_new(); assert( rsa_ ); Copy( rsa_, p.rsa_ ); return *this; } //Buffer RSACrypto::PublicKey::GetN() //{ // if ( rsa_ ) // { // int len = BN_num_bytes( rsa_->n ); // Buffer n = Buffer::Alloc( len ); // if ( NULL == n.buf ) // { // return Buffer(); // } // BN_bn2bin( rsa_->n, (unsigned char *)n.buf ); // return n; // } // return Buffer(); //} //Buffer RSACrypto::PublicKey::GetE() //{ // if ( rsa_ ) // { // int len = BN_num_bytes( rsa_->e ); // Buffer e = Buffer::Alloc( len ); // if ( NULL == e.buf ) // { // return Buffer(); // } // BN_bn2bin( rsa_->e, (unsigned char *)e.buf ); // return e; // } // return Buffer(); //} RSACrypto::PublicKey::PublicKey() : rsa_( NULL ) { } RSA* RSACrypto::PublicKey::Alloc() { RSA* rsa = RSA_new(); assert( rsa ); #if OPENSSL_VERSION_NUMBER < 0x10100000L rsa->n = BN_new(); rsa->e = BN_new(); #else BIGNUM* n = BN_new(), * e = BN_new(); RSA_set0_key(rsa, n, e, NULL); #endif return rsa; } void RSACrypto::PublicKey::Free(rsa_st* p) { if ( p ) { RSA_free( p ); } } void RSACrypto::PublicKey::Copy(rsa_st* to, const rsa_st* from) { #if OPENSSL_VERSION_NUMBER < 0x10100000L BN_copy(to->n, from->n); BN_copy(to->e, from->e); #else BIGNUM* to_n, * to_e,* to_d; const BIGNUM* from_n = RSA_get0_n(from), * from_e = RSA_get0_e(from); RSA_get0_key(to, (const BIGNUM**)&to_n, (const BIGNUM**)&to_e, (const BIGNUM**)&to_d); BN_copy(to_n, from_n); BN_copy(to_e, from_e); RSA_set0_key(to, to_n, to_e, to_d); #endif } RSACrypto::PrivateKey::PrivateKey() : rsa_( NULL ) { } RSACrypto::PrivateKey::PrivateKey(rsa_st* rsa) : rsa_( rsa ) { } RSACrypto::PrivateKey::~PrivateKey() { if ( rsa_ ) { RSA_free( rsa_ ); rsa_ = NULL; } } RSA* RSACrypto::PrivateKey::Alloc() { RSA* rsa = RSA_new(); assert( rsa ); #if OPENSSL_VERSION_NUMBER < 0x10100000L rsa->d = BN_new(); rsa->p = BN_new(); rsa->q = BN_new(); #else BIGNUM* d = BN_new(), * p = BN_new(), * q = BN_new(); RSA_set0_key(rsa, NULL, NULL, d); RSA_set0_factors(rsa, p, q); #endif return rsa; } Buffer RSACrypto::EncryptPublic(const RSACrypto::PublicKey* k, const unsigned char* plain, int plainLen) { int rsaSize = RSA_size( k->rsa_ ); Buffer cipherText = Buffer::Alloc( rsaSize ); if ( NULL == cipherText.buf ) { return Buffer(); } // must be checked when RSA_PKCS1_OAEP_PADDING mode if ( plainLen >= rsaSize - 41 ) { Buffer::Free(cipherText); assert(false); return Buffer(); } int cipherTextLen = RSA_public_encrypt( plainLen, plain, (unsigned char *)cipherText.buf, k->rsa_, RSA_PKCS1_OAEP_PADDING); if ( -1 == cipherTextLen ) { Buffer::Free(cipherText); return Buffer(); } assert( cipherTextLen == rsaSize ); //XSystem::MemoryPool::MemoryPool_Realloc( cipherText, cipherTextLen ); return cipherText; } Buffer RSACrypto::DecryptPrivate(const RSACrypto::PrivateKey* k, const unsigned char* cipher, int cipherLen) { int rsaSize = RSA_size( k->rsa_ ); Buffer plainText = Buffer::Alloc( rsaSize ); if ( NULL == plainText.buf ) { return Buffer(); } int plainTextLen = RSA_private_decrypt( cipherLen, cipher, (unsigned char *)plainText.buf, k->rsa_, RSA_PKCS1_OAEP_PADDING); if ( -1 == plainTextLen ) { Buffer::Free(plainText); return Buffer(); } plainText.len = plainTextLen; return plainText; } Buffer RSACrypto::EncryptPrivate(const RSACrypto::PrivateKey* k, const unsigned char* plain, int plainLen) { int rsaSize = RSA_size( k->rsa_ ); Buffer cipherText = Buffer::Alloc( rsaSize ); if ( NULL == cipherText.buf ) { return Buffer(); } // must be checked when RSA_PKCS1_PADDING mode (private encrypt¿¡¼­´Â ´Ù¸¥ paddingÀ» Áö¿ø¾ÈÇÑ´Ù.) if ( plainLen >= rsaSize - 11 ) { Buffer::Free(cipherText); assert(false); return Buffer(); } int cipherTextLen = RSA_private_encrypt( plainLen, plain, (unsigned char *)cipherText.buf, k->rsa_, RSA_PKCS1_PADDING); if ( -1 == cipherTextLen ) { Buffer::Free(cipherText); return Buffer(); } assert( cipherTextLen == rsaSize ); //XSystem::MemoryPool::MemoryPool_Realloc( cipherText, cipherTextLen ); return cipherText; } Buffer RSACrypto::DecryptPublic(const RSACrypto::PublicKey* k, const unsigned char* cipher, int cipherLen) { int rsaSize = RSA_size( k->rsa_ ); Buffer plainText = Buffer::Alloc( rsaSize ); if ( NULL == plainText.buf ) { return Buffer(); } int plainTextLen = RSA_public_decrypt( cipherLen, cipher, (unsigned char *)plainText.buf, k->rsa_, RSA_PKCS1_PADDING); if ( -1 == plainTextLen ) { Buffer::Free(plainText); return Buffer(); } plainText.len = plainTextLen; return plainText; } bool RSACrypto::GenerateKey(RSACrypto::PublicKey* publicKey, RSACrypto::PrivateKey* privateKey) { RSA* rsa = RSA_generate_key( 1024, 7, NULL, NULL ); if ( NULL == rsa ) { //ERR_get_error(); return false; } if ( 1 != RSA_check_key( rsa ) ) { //ERR_get_error(); return false; } publicKey->rsa_ = publicKey->Alloc(); publicKey->Copy( publicKey->rsa_, rsa ); privateKey->rsa_ = rsa; #ifdef _DEBUG // printf("n:"); // BN_print_fp(stdout, publicKey->rsa_->n); // printf(""); // printf("e:"); // BN_print_fp(stdout, publicKey->rsa_->e); // printf(""); //char buf[1024]; //BIO* bp = BIO_new_mem_buf(buf, sizeof(buf)); //PEM_write_bio_RSAPrivateKey(bp, rsa, 0, 0, 0, 0, 0); //PEM_read_bio_RSAPrivateKey(bp, ) #endif return true; } bool RSACrypto::PrintKey(const PublicKey* k, std::string& e, std::string& n) { #if OPENSSL_VERSION_NUMBER < 0x10100000L char* tmp = BN_bn2hex(k->rsa_->e); #else const BIGNUM* rsa_e = RSA_get0_e(k->rsa_); char* tmp = BN_bn2hex(rsa_e); #endif if (!tmp) { return false; } e = tmp; #if OPENSSL_VERSION_NUMBER < 0x10100000L tmp = BN_bn2hex(k->rsa_->n); #else const BIGNUM* rsa_n = RSA_get0_n(k->rsa_); tmp = BN_bn2hex(rsa_n); #endif if (!tmp) { return false; } n = tmp; return true; } bool RSACrypto::PrintKey(const PrivateKey* k, std::string& n, std::string& e, std::string& d) { #if OPENSSL_VERSION_NUMBER < 0x10100000L char* tmp = BN_bn2hex(k->rsa_->n); #else const BIGNUM* rsa_n = RSA_get0_n(k->rsa_); char* tmp = BN_bn2hex(rsa_n); #endif if (!tmp) { return false; } n = tmp; #if OPENSSL_VERSION_NUMBER < 0x10100000L tmp = BN_bn2hex(k->rsa_->e); #else const BIGNUM* rsa_e = RSA_get0_e(k->rsa_); tmp = BN_bn2hex(rsa_e); #endif if (!tmp) { return false; } e = tmp; #if OPENSSL_VERSION_NUMBER < 0x10100000L tmp = BN_bn2hex(k->rsa_->d); #else const BIGNUM* rsa_d = RSA_get0_d(k->rsa_); tmp = BN_bn2hex(rsa_d); #endif if (!tmp) { return false; } d = tmp; return true; } bool RSACrypto::StorePrivateKey(const PrivateKey* k, char* buf, size_t& buflen) { // DER Æ÷¸ËÀ¸·Î º¯È¯ char* tmp = NULL; int n = i2d_RSAPrivateKey(k->rsa_, (unsigned char **)&tmp); if (n < 0) { return false; } if (n > (int)buflen) { printf("RSACrypto::StorePrivateKey: buflen is too small\n"); return false; } memcpy(buf, tmp, n); buflen = n; free(tmp); return true; } bool RSACrypto::RestorePrivateKey(const char* buf, size_t buflen, PrivateKey* k) { // DER Æ÷¸Ë¿¡¼­ º¯È¯ char* tmp = (char *)malloc(buflen); if (!tmp) { return false; } memcpy(tmp, buf, buflen); if (!d2i_RSAPrivateKey(&k->rsa_, (const unsigned char **)&tmp, buflen)) { free(tmp); return false; } return true; } bool RSACrypto::StorePublicKey(const PublicKey* k, char* buf, size_t& buflen) { // DER Æ÷¸ËÀ¸·Î º¯È¯ char* tmp = NULL; int n = i2d_RSAPublicKey(k->rsa_, (unsigned char **)&tmp); if (n < 0) { return false; } if (n > (int)buflen) { printf("RSACrypto::StorePublicKey: buflen is too small\n"); return false; } memcpy(buf, tmp, n); buflen = n; free(tmp); return true; } bool RSACrypto::RestorePublicKey(const char* buf, size_t buflen, PublicKey* k) { // DER Æ÷¸Ë¿¡¼­ º¯È¯ char* tmp = (char *)malloc(buflen); if (!tmp) { return false; } memcpy(tmp, buf, buflen); if (!d2i_RSAPublicKey(&k->rsa_, (const unsigned char **)&tmp, buflen)) { free(tmp); return false; } return true; } Buffer SHA1::Digest(const Buffer& plain) { Buffer result = Buffer::Alloc( 20 ); ::SHA1( (const unsigned char *)plain.buf, (unsigned long)plain.len, (unsigned char *)result.buf); return result; } }