--- ./RSA.pm 2011-08-25 02:00:07.000000000 +0300 +++ ./RSA.pm 2017-03-24 23:24:34.636751000 +0200 @@ -14,8 +14,31 @@ bootstrap Crypt::OpenSSL::RSA $VERSION; +sub new_private_key { + + my ($self, $keystring, $passin) = @_; + + if (length ($passin) > 0 ) { + return $self->_new_enc_private_key($keystring, $passin); + } + return $self->_new_private_key($keystring); +} + +sub get_private_key_string { + + my ($self, $passout, $cipher) = @_; + + if (length ($passout) > 0 && length ($cipher) > 0) { + return $self->_get_enc_private_key_string($passout, $cipher); + } elsif (length $passout > 0) { + return $self->_get_enc_private_key_string($passout, "aes-256-cbc"); + } + return $self->_get_private_key_string(); +} + BEGIN { eval { require Crypt::OpenSSL::Bignum; }; } + 1; __END__ @@ -96,7 +119,9 @@ } } -=item new_private_key +=item new_private_key(privkey_string) +=cut +=item new_private_key(privkey_string, password) Create a new Crypt::OpenSSL::RSA object by loading a private key in from an string containing the Base64/DER encoding of the PKCS1 @@ -179,8 +204,14 @@ and is the format that is produced by running C. =item get_private_key_string +=cut +=item get_enc_private_key_string(password) +=cut +=item get_enc_private_key_string(password, cipher) -Return the DER-encoded PKCS1 representation of the private key. +Return the unencripted or encripted DER-encoded PKCS1 representation +of the private key. For stoping of potential leak unencrypted private key +if cipher name is unknown will use DES3 (DES-EDE3) cipher. =item encrypt --- ./RSA.xs 2011-08-25 01:57:35.000000000 +0300 +++ ./RSA.xs 2017-03-24 23:24:34.644786000 +0200 @@ -179,6 +179,30 @@ return rsa; } + +RSA* _load_enc_rsa_key(SV* p_keyStringSv, + RSA*(*p_loader)(BIO*, RSA**, pem_password_cb*, void*), char* password) +{ + STRLEN keyStringLength; + char* keyString; + + RSA* rsa; + BIO* stringBIO; + + keyString = SvPV(p_keyStringSv, keyStringLength); + + CHECK_OPEN_SSL(stringBIO = BIO_new_mem_buf(keyString, keyStringLength)); + + rsa = p_loader(stringBIO, NULL, NULL, password); + + CHECK_OPEN_SSL(BIO_set_close(stringBIO, BIO_CLOSE) == 1); + BIO_free(stringBIO); + + CHECK_OPEN_SSL(rsa); + return rsa; +} + + SV* rsa_crypt(rsaData* p_rsa, SV* p_from, int (*p_crypt)(int, const unsigned char*, unsigned char*, RSA*, int)) { @@ -214,7 +238,7 @@ ERR_load_crypto_strings(); SV* -new_private_key(proto, key_string_SV) +_new_private_key(proto, key_string_SV) SV* proto; SV* key_string_SV; CODE: @@ -223,6 +247,23 @@ OUTPUT: RETVAL + +SV* +_new_enc_private_key(proto, key_string_SV, password_SV) + SV* proto; + SV* key_string_SV; + SV* password_SV; + PREINIT: + char* password; + CODE: + password = SvPV_nolen(password_SV); + + RETVAL = make_rsa_obj( + proto, _load_enc_rsa_key(key_string_SV, PEM_read_bio_RSAPrivateKey, password)); + OUTPUT: + RETVAL + + SV* _new_public_key_pkcs1(proto, key_string_SV) SV* proto; @@ -251,7 +292,7 @@ Safefree(p_rsa); SV* -get_private_key_string(p_rsa) +_get_private_key_string(p_rsa) rsaData* p_rsa; PREINIT: BIO* stringBIO; @@ -264,6 +305,32 @@ OUTPUT: RETVAL + +SV* +_get_enc_private_key_string(p_rsa, passout_SV, cipher_SV) + rsaData* p_rsa; + SV* passout_SV; + SV* cipher_SV; + PREINIT: + char* passout; + char* cipher; + + BIO* stringBIO; + const EVP_CIPHER *enc; + CODE: + passout = SvPV_nolen(passout_SV); + cipher = SvPV_nolen(cipher_SV); + + CHECK_OPEN_SSL(stringBIO = BIO_new(BIO_s_mem())); + enc = EVP_get_cipherbyname(cipher); + if (enc == NULL) { enc = EVP_get_cipherbyname("DES3"); } + PEM_write_bio_RSAPrivateKey( + stringBIO, p_rsa->rsa, enc, NULL, 0, NULL, passout); + RETVAL = extractBioString(stringBIO); + + OUTPUT: + RETVAL + SV* get_public_key_string(p_rsa) rsaData* p_rsa; --- ./t/rsa.t 2011-08-25 01:57:35.000000000 +0300 +++ ./t/rsa.t 2017-03-24 23:40:30.761508000 +0200 @@ -4,7 +4,7 @@ use Crypt::OpenSSL::Random; use Crypt::OpenSSL::RSA; -BEGIN { plan tests => 43 + (UNIVERSAL::can("Crypt::OpenSSL::RSA", "use_sha512_hash") ? 4*5 : 0) } +BEGIN { plan tests => 46 + (UNIVERSAL::can("Crypt::OpenSSL::RSA", "use_sha512_hash") ? 4*5 : 0) } sub _Test_Encrypt_And_Decrypt { @@ -84,6 +84,15 @@ ok($private_key_string and $public_key_string); +my $enc_private_key_string_default = $rsa->get_private_key_string('12345'); +ok($enc_private_key_string_default); + +my $enc_private_key_string_des3 = $rsa->get_private_key_string('12345', 'des3-cbc'); +ok($enc_private_key_string_des3); + +my $enc_private_key_string_idea = $rsa->get_private_key_string('12345', 'IDEA'); +ok($enc_private_key_string_idea); + my $plaintext = "The quick brown fox jumped over the lazy dog"; my $rsa_priv = Crypt::OpenSSL::RSA->new_private_key($private_key_string); ok($plaintext eq $rsa_priv->decrypt($rsa_priv->encrypt($plaintext)));