CC: | onborodin [...] gmail.com |
Subject: | Patch to add functions to work with private keys |
See attached patch. See also:
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=220136
Subject: | rsa.diff |
--- ./RSA.pm.orig 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<openssl rsa -pubout>.
=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.orig 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.orig 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)));