Crypt-OpenSSL-RSA-0.35/0000755000000000000000000000000015006707567013161 5ustar rootrootCrypt-OpenSSL-RSA-0.35/README.md0000644000000000000000000002207514261733635014443 0ustar rootroot[![Build Status](https://travis-ci.org/toddr/Crypt-OpenSSL-RSA.png?branch=master)](https://travis-ci.org/toddr/Crypt-OpenSSL-RSA) # NAME Crypt::OpenSSL::RSA - RSA encoding and decoding, using the openSSL libraries # SYNOPSIS use Crypt::OpenSSL::Random; use Crypt::OpenSSL::RSA; # not necessary if we have /dev/random: Crypt::OpenSSL::Random::random_seed($good_entropy); Crypt::OpenSSL::RSA->import_random_seed(); $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($key_string); $ciphertext = $rsa->encrypt($plaintext); $rsa_priv = Crypt::OpenSSL::RSA->new_private_key($key_string); $plaintext = $rsa->encrypt($ciphertext); $rsa = Crypt::OpenSSL::RSA->generate_key(1024); # or $rsa = Crypt::OpenSSL::RSA->generate_key(1024, $prime); print "private key is:\n", $rsa->get_private_key_string(); print "public key (in PKCS1 format) is:\n", $rsa->get_public_key_string(); print "public key (in X509 format) is:\n", $rsa->get_public_key_x509_string(); $rsa_priv->use_md5_hash(); # insecure. use_sha256_hash or use_sha1_hash are the default $signature = $rsa_priv->sign($plaintext); print "Signed correctly\n" if ($rsa->verify($plaintext, $signature)); # DESCRIPTION `Crypt::OpenSSL::RSA` provides the ability to RSA encrypt strings which are somewhat shorter than the block size of a key. It also allows for decryption, signatures and signature verification. _NOTE_: Many of the methods in this package can croak, so use `eval`, or Error.pm's try/catch mechanism to capture errors. Also, while some methods from earlier versions of this package return true on success, this (never documented) behavior is no longer the case. # Class Methods - new\_public\_key Create a new `Crypt::OpenSSL::RSA` object by loading a public key in from a string containing Base64/DER-encoding of either the PKCS1 or X.509 representation of the key. The string should include the `-----BEGIN...-----` and `-----END...-----` lines. The padding is set to PKCS1\_OAEP, but can be changed with the `use_xxx_padding` methods. - new\_private\_key Create a new `Crypt::OpenSSL::RSA` object by loading a private key in from an string containing the Base64/DER encoding of the PKCS1 representation of the key. The string should include the `-----BEGIN...-----` and `-----END...-----` lines. The padding is set to PKCS1\_OAEP, but can be changed with `use_xxx_padding`. An optional parameter can be passed for passphase protected private key: - passphase The passphase which protects the private key. - generate\_key Create a new `Crypt::OpenSSL::RSA` object by constructing a private/public key pair. The first (mandatory) argument is the key size, while the second optional argument specifies the public exponent (the default public exponent is 65537). The padding is set to `PKCS1_OAEP`, but can be changed with use\_xxx\_padding methods. - new\_key\_from\_parameters Given [Crypt::OpenSSL::Bignum](https://metacpan.org/pod/Crypt%3A%3AOpenSSL%3A%3ABignum) objects for n, e, and optionally d, p, and q, where p and q are the prime factors of n, e is the public exponent and d is the private exponent, create a new Crypt::OpenSSL::RSA object using these values. If p and q are provided and d is undef, d is computed. Note that while p and q are not necessary for a private key, their presence will speed up computation. - import\_random\_seed Import a random seed from [Crypt::OpenSSL::Random](https://metacpan.org/pod/Crypt%3A%3AOpenSSL%3A%3ARandom), since the OpenSSL libraries won't allow sharing of random structures across perl XS modules. # Instance Methods - DESTROY Clean up after ourselves. In particular, erase and free the memory occupied by the RSA key structure. - get\_public\_key\_string Return the Base64/DER-encoded PKCS1 representation of the public key. This string has header and footer lines: -----BEGIN RSA PUBLIC KEY------ -----END RSA PUBLIC KEY------ - get\_public\_key\_x509\_string Return the Base64/DER-encoded representation of the "subject public key", suitable for use in X509 certificates. This string has header and footer lines: -----BEGIN PUBLIC KEY------ -----END PUBLIC KEY------ and is the format that is produced by running `openssl rsa -pubout`. - get\_private\_key\_string Return the Base64/DER-encoded PKCS1 representation of the private key. This string has header and footer lines: -----BEGIN RSA PRIVATE KEY------ -----END RSA PRIVATE KEY------ 2 optional parameters can be passed for passphase protected private key string: - passphase The passphase which protects the private key. - cipher name The cipher algorithm used to protect the private key. Default to 'des3'. - encrypt Encrypt a binary "string" using the public (portion of the) key. - decrypt Decrypt a binary "string". Croaks if the key is public only. - private\_encrypt Encrypt a binary "string" using the private key. Croaks if the key is public only. - public\_decrypt Decrypt a binary "string" using the public (portion of the) key. - sign Sign a string using the secret (portion of the) key. - verify Check the signature on a text. - use\_no\_padding Use raw RSA encryption. This mode should only be used to implement cryptographically sound padding modes in the application code. Encrypting user data directly with RSA is insecure. - use\_pkcs1\_padding Use PKCS #1 v1.5 padding. This currently is the most widely used mode of padding. - use\_pkcs1\_oaep\_padding Use `EME-OAEP` padding as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding parameter. This mode of padding is recommended for all new applications. It is the default mode used by `Crypt::OpenSSL::RSA`. - use\_sslv23\_padding Use `PKCS #1 v1.5` padding with an SSL-specific modification that denotes that the server is SSL3 capable. Not available since OpenSSL 3. - use\_md5\_hash Use the RFC 1321 MD5 hashing algorithm by Ron Rivest when signing and verifying messages. Note that this is considered **insecure**. - use\_sha1\_hash Use the RFC 3174 Secure Hashing Algorithm (FIPS 180-1) when signing and verifying messages. This is the default, when use\_sha256\_hash is not available. - use\_sha224\_hash, use\_sha256\_hash, use\_sha384\_hash, use\_sha512\_hash These FIPS 180-2 hash algorithms, for use when signing and verifying messages, are only available with newer openssl versions (>= 0.9.8). use\_sha256\_hash is the default hash mode when available. - use\_ripemd160\_hash Dobbertin, Bosselaers and Preneel's RIPEMD hashing algorithm when signing and verifying messages. - use\_whirlpool\_hash Vincent Rijmen und Paulo S. L. M. Barreto ISO/IEC 10118-3:2004 WHIRLPOOL hashing algorithm when signing and verifying messages. - size Returns the size, in bytes, of the key. All encrypted text will be of this size, and depending on the padding mode used, the length of the text to be encrypted should be: - pkcs1\_oaep\_padding at most 42 bytes less than this size. - pkcs1\_padding or sslv23\_padding at most 11 bytes less than this size. - no\_padding exactly this size. - check\_key This function validates the RSA key, returning a true value if the key is valid, and a false value otherwise. Croaks if the key is public only. - get\_key\_parameters Return `Crypt::OpenSSL::Bignum` objects representing the values of `n`, `e`, `d`, `p`, `q`, `d mod (p-1)`, `d mod (q-1)`, and `1/q mod p`, where `p` and `q` are the prime factors of `n`, `e` is the public exponent and `d` is the private exponent. Some of these values may return as `undef`; only `n` and `e` will be defined for a public key. The `Crypt::OpenSSL::Bignum` module must be installed for this to work. - is\_private Return true if this is a private key, and false if it is private only. # BUGS There is a small memory leak when generating new keys of more than 512 bits. # AUTHOR Ian Robertson, `iroberts@cpan.org`. For support, please email `perl-openssl-users@lists.sourceforge.net`. # ACKNOWLEDGEMENTS # LICENSE Copyright (c) 2001-2011 Ian Robertson. Crypt::OpenSSL::RSA is free software; you may redistribute it and/or modify it under the same terms as Perl itself. # SEE ALSO [perl(1)](http://man.he.net/man1/perl), [Crypt::OpenSSL::Random](https://metacpan.org/pod/Crypt%3A%3AOpenSSL%3A%3ARandom), [Crypt::OpenSSL::Bignum](https://metacpan.org/pod/Crypt%3A%3AOpenSSL%3A%3ABignum), [rsa(3)](http://man.he.net/man3/rsa), [RSA\_new(3)](http://man.he.net/?topic=RSA_new§ion=3), [RSA\_public\_encrypt(3)](http://man.he.net/?topic=RSA_public_encrypt§ion=3), [RSA\_size(3)](http://man.he.net/?topic=RSA_size§ion=3), [RSA\_generate\_key(3)](http://man.he.net/?topic=RSA_generate_key§ion=3), [RSA\_check\_key(3)](http://man.he.net/?topic=RSA_check_key§ion=3) Crypt-OpenSSL-RSA-0.35/RSA.pm0000644000000000000000000002411315006702054014127 0ustar rootrootpackage Crypt::OpenSSL::RSA; use strict; use warnings; use Carp; # Removing carp will break the XS code. our $VERSION = '0.35'; use XSLoader; XSLoader::load 'Crypt::OpenSSL::RSA', $VERSION; BEGIN { eval { local $SIG{__DIE__}; # prevent outer handlers from being called require Crypt::OpenSSL::Bignum; }; } ## no critic qw(RequireCheckingReturnValueOfEval); sub new_public_key { my ( $proto, $p_key_string ) = @_; if ( $p_key_string =~ /^-----BEGIN RSA PUBLIC KEY-----/ ) { return $proto->_new_public_key_pkcs1($p_key_string); } elsif ( $p_key_string =~ /^-----BEGIN PUBLIC KEY-----/ ) { return $proto->_new_public_key_x509($p_key_string); } else { croak "unrecognized key format"; } } sub new_key_from_parameters { my ( $proto, $n, $e, $d, $p, $q ) = @_; return $proto->_new_key_from_parameters( map { $_ ? $_->pointer_copy() : 0 } $n, $e, $d, $p, $q ); } sub import_random_seed { until ( _random_status() ) { _random_seed( Crypt::OpenSSL::Random::random_bytes(20) ); } } sub get_key_parameters { return map { $_ ? Crypt::OpenSSL::Bignum->bless_pointer($_) : undef } shift->_get_key_parameters(); } 1; __END__ =head1 NAME Crypt::OpenSSL::RSA - RSA encoding and decoding, using the openSSL libraries =head1 SYNOPSIS use Crypt::OpenSSL::Random; use Crypt::OpenSSL::RSA; # not necessary if we have /dev/random: Crypt::OpenSSL::Random::random_seed($good_entropy); Crypt::OpenSSL::RSA->import_random_seed(); $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($key_string); $ciphertext = $rsa->encrypt($plaintext); $rsa_priv = Crypt::OpenSSL::RSA->new_private_key($key_string); $plaintext = $rsa->decrypt($ciphertext); $rsa = Crypt::OpenSSL::RSA->generate_key(1024); # or $rsa = Crypt::OpenSSL::RSA->generate_key(1024, $prime); print "private key is:\n", $rsa->get_private_key_string(); print "public key (in PKCS1 format) is:\n", $rsa->get_public_key_string(); print "public key (in X509 format) is:\n", $rsa->get_public_key_x509_string(); $rsa_priv->use_md5_hash(); # insecure. use_sha256_hash or use_sha1_hash are the default $signature = $rsa_priv->sign($plaintext); print "Signed correctly\n" if ($rsa->verify($plaintext, $signature)); =head1 SECURITY Version 0.35 makes the use of PKCS#1 v1.5 padding a fatal error. It is very difficult to implement PKCS#1 v1.5 padding securely. If you are still using RSA in in general, you should be looking at alternative encryption algorithms. =head1 DESCRIPTION C provides the ability to RSA encrypt strings which are somewhat shorter than the block size of a key. It also allows for decryption, signatures and signature verification. I: Many of the methods in this package can croak, so use C, or Error.pm's try/catch mechanism to capture errors. Also, while some methods from earlier versions of this package return true on success, this (never documented) behavior is no longer the case. =head1 Class Methods =over =item new_public_key Create a new C object by loading a public key in from a string containing Base64/DER-encoding of either the PKCS1 or X.509 representation of the key. The string should include the C<-----BEGIN...-----> and C<-----END...-----> lines. The padding is set to PKCS1_OAEP, but can be changed with the C methods. =item new_private_key Create a new C object by loading a private key in from an string containing the Base64/DER encoding of the PKCS1 representation of the key. The string should include the C<-----BEGIN...-----> and C<-----END...-----> lines. The padding is set to PKCS1_OAEP, but can be changed with C. An optional parameter can be passed for passphase protected private key: =over =item passphase The passphase which protects the private key. =back =item generate_key Create a new C object by constructing a private/public key pair. The first (mandatory) argument is the key size, while the second optional argument specifies the public exponent (the default public exponent is 65537). The padding is set to C, but can be changed with use_xxx_padding methods. =item new_key_from_parameters Given L objects for n, e, and optionally d, p, and q, where p and q are the prime factors of n, e is the public exponent and d is the private exponent, create a new Crypt::OpenSSL::RSA object using these values. If p and q are provided and d is undef, d is computed. Note that while p and q are not necessary for a private key, their presence will speed up computation. =item import_random_seed Import a random seed from L, since the OpenSSL libraries won't allow sharing of random structures across perl XS modules. =back =head1 Instance Methods =over =item DESTROY Clean up after ourselves. In particular, erase and free the memory occupied by the RSA key structure. =item get_public_key_string Return the Base64/DER-encoded PKCS1 representation of the public key. This string has header and footer lines: -----BEGIN RSA PUBLIC KEY------ -----END RSA PUBLIC KEY------ =item get_public_key_x509_string Return the Base64/DER-encoded representation of the "subject public key", suitable for use in X509 certificates. This string has header and footer lines: -----BEGIN PUBLIC KEY------ -----END PUBLIC KEY------ and is the format that is produced by running C. =item get_private_key_string Return the Base64/DER-encoded PKCS1 representation of the private key. This string has header and footer lines: -----BEGIN RSA PRIVATE KEY------ -----END RSA PRIVATE KEY------ 2 optional parameters can be passed for passphase protected private key string: =over =item passphase The passphase which protects the private key. =item cipher name The cipher algorithm used to protect the private key. Default to 'des3'. =back =item encrypt Encrypt a binary "string" using the public (portion of the) key. =item decrypt Decrypt a binary "string". Croaks if the key is public only. =item private_encrypt Encrypt a binary "string" using the private key. Croaks if the key is public only. =item public_decrypt Decrypt a binary "string" using the public (portion of the) key. =item sign Sign a string using the secret (portion of the) key. =item verify Check the signature on a text. =item use_no_padding Use raw RSA encryption. This mode should only be used to implement cryptographically sound padding modes in the application code. Encrypting user data directly with RSA is insecure. =item use_pkcs1_padding PKCS #1 v1.5 padding has been disabled as it is nearly impossible to use this padding method in a secure manner. It is known to be vulnerable to timing based side channel attacks. use_pkcs1_padding() results in a fatal error. L =item use_pkcs1_oaep_padding Use C padding as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding parameter. This mode of padding is recommended for all new applications. It is the default mode used by C. =item use_sslv23_padding Use C padding with an SSL-specific modification that denotes that the server is SSL3 capable. Not available since OpenSSL 3. =item use_md5_hash Use the RFC 1321 MD5 hashing algorithm by Ron Rivest when signing and verifying messages. Note that this is considered B. =item use_sha1_hash Use the RFC 3174 Secure Hashing Algorithm (FIPS 180-1) when signing and verifying messages. This is the default, when use_sha256_hash is not available. =item use_sha224_hash, use_sha256_hash, use_sha384_hash, use_sha512_hash These FIPS 180-2 hash algorithms, for use when signing and verifying messages, are only available with newer openssl versions (>= 0.9.8). use_sha256_hash is the default hash mode when available. =item use_ripemd160_hash Dobbertin, Bosselaers and Preneel's RIPEMD hashing algorithm when signing and verifying messages. =item use_whirlpool_hash Vincent Rijmen und Paulo S. L. M. Barreto ISO/IEC 10118-3:2004 WHIRLPOOL hashing algorithm when signing and verifying messages. =item size Returns the size, in bytes, of the key. All encrypted text will be of this size, and depending on the padding mode used, the length of the text to be encrypted should be: =over =item pkcs1_oaep_padding at most 42 bytes less than this size. =item pkcs1_padding or sslv23_padding at most 11 bytes less than this size. =item no_padding exactly this size. =back =item check_key This function validates the RSA key, returning a true value if the key is valid, and a false value otherwise. Croaks if the key is public only. =item get_key_parameters Return C objects representing the values of C, C, C, C

, C, C, C, and C<1/q mod p>, where C

and C are the prime factors of C, C is the public exponent and C is the private exponent. Some of these values may return as C; only C and C will be defined for a public key. The C module must be installed for this to work. =item is_private Return true if this is a private key, and false if it is private only. =back =head1 BUGS There is a small memory leak when generating new keys of more than 512 bits. =head1 AUTHOR Ian Robertson, C. For support, please email C. =head1 ACKNOWLEDGEMENTS =head1 LICENSE Copyright (c) 2001-2011 Ian Robertson. Crypt::OpenSSL::RSA is free software; you may redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, L, L, L, L, L, L, L, L =cut Crypt-OpenSSL-RSA-0.35/RSA.xs0000644000000000000000000006640015006702011014143 0ustar rootroot#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include #include #include #include #include #include #include #if OPENSSL_VERSION_NUMBER < 0x30000000 #include #endif #include #include #include #include #if OPENSSL_VERSION_NUMBER >= 0x30000000L #include #include #include #endif #if OPENSSL_VERSION_NUMBER >= 0x30000000L #define UNSIGNED_CHAR unsigned char #define SIZE_T_INT size_t #define SIZE_T_UNSIGNED_INT size_t #define EVP_PKEY EVP_PKEY #define EVP_PKEY_free(p) EVP_PKEY_free(p) #define EVP_PKEY_get_size(p) EVP_PKEY_get_size(p) #define PEM_read_bio_PrivateKey PEM_read_bio_PrivateKey #define PEM_read_bio_RSAPublicKey PEM_read_bio_PUBKEY #define PEM_read_bio_RSA_PUBKEY PEM_read_bio_PUBKEY #define PEM_write_bio_PUBKEY(o,p) PEM_write_bio_PUBKEY(o,p); #define PEM_write_bio_PrivateKey_traditional(m, n, o, p, q, r, s) PEM_write_bio_PrivateKey_traditional(m, n, o, p, q, r, s) #else #define UNSIGNED_CHAR char #define SIZE_T_INT int #define SIZE_T_UNSIGNED_INT unsigned int #define EVP_PKEY RSA #define EVP_PKEY_free(p) RSA_free(p) #define EVP_PKEY_get_size(p) RSA_size(p) #define PEM_read_bio_PrivateKey PEM_read_bio_RSAPrivateKey #define PEM_read_bio_RSAPublicKey PEM_read_bio_RSAPublicKey #define PEM_read_bio_RSA_PUBKEY PEM_read_bio_RSA_PUBKEY #define PEM_write_bio_PUBKEY(o,p) PEM_write_bio_RSA_PUBKEY(o,p) #define PEM_write_bio_PrivateKey_traditional(m, n, o, p, q, r, s) PEM_write_bio_RSAPrivateKey(m, n , o, p, q, r, s) #endif typedef struct { EVP_PKEY* rsa; int padding; int hashMode; } rsaData; /* Key names for the rsa hash structure */ #define KEY_KEY "_Key" #define PADDING_KEY "_Padding" #define HASH_KEY "_Hash_Mode" #define PACKAGE_NAME "Crypt::OpenSSL::RSA" #define OLD_CRUFTY_SSL_VERSION (OPENSSL_VERSION_NUMBER < 0x10100000L || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x03050000fL)) void croakSsl(char* p_file, int p_line) { const char* errorReason; /* Just return the top error on the stack */ errorReason = ERR_reason_error_string(ERR_get_error()); ERR_clear_error(); croak("%s:%d: OpenSSL error: %s", p_file, p_line, errorReason); } #define CHECK_OPEN_SSL(p_result) if (!(p_result)) croakSsl(__FILE__, __LINE__); #define PACKAGE_CROAK(p_message) croak("%s", (p_message)) #define CHECK_NEW(p_var, p_size, p_type) \ if (New(0, p_var, p_size, p_type) == NULL) \ { PACKAGE_CROAK("unable to alloc buffer"); } #define THROW(p_result) if (!(p_result)) { error = 1; goto err; } char _is_private(rsaData* p_rsa) { char ret = 0; #if OLD_CRUFTY_SSL_VERSION const BIGNUM* d; d = p_rsa->rsa->d; ret = (d != NULL); #else #if OPENSSL_VERSION_NUMBER >= 0x30000000L BIGNUM* d = NULL; EVP_PKEY_get_bn_param(p_rsa->rsa, OSSL_PKEY_PARAM_RSA_D, &d); ret = (d != NULL); BN_clear_free(d); #else const BIGNUM* d = NULL; RSA_get0_key(p_rsa->rsa, NULL, NULL, &d); ret = (d != NULL); #endif #endif return ret; } SV* make_rsa_obj(SV* p_proto, EVP_PKEY* p_rsa) { rsaData* rsa; CHECK_NEW(rsa, 1, rsaData); rsa->rsa = p_rsa; rsa->hashMode = NID_sha1; rsa->padding = RSA_PKCS1_OAEP_PADDING; return sv_bless( newRV_noinc(newSViv((IV) rsa)), (SvROK(p_proto) ? SvSTASH(SvRV(p_proto)) : gv_stashsv(p_proto, 1))); } int get_digest_length(int hash_method) { switch(hash_method) { case NID_md5: return MD5_DIGEST_LENGTH; break; case NID_sha1: return SHA_DIGEST_LENGTH; break; #ifdef SHA512_DIGEST_LENGTH case NID_sha224: return SHA224_DIGEST_LENGTH; break; case NID_sha256: return SHA256_DIGEST_LENGTH; break; case NID_sha384: return SHA384_DIGEST_LENGTH; break; case NID_sha512: return SHA512_DIGEST_LENGTH; break; #endif case NID_ripemd160: return RIPEMD160_DIGEST_LENGTH; break; #ifdef WHIRLPOOL_DIGEST_LENGTH case NID_whirlpool: return WHIRLPOOL_DIGEST_LENGTH; break; #endif default: croak("Unknown digest hash mode %u", hash_method); break; } } #if OPENSSL_VERSION_NUMBER >= 0x30000000L EVP_MD *get_md_bynid(int hash_method) { switch(hash_method) { case NID_md5: return EVP_MD_fetch(NULL, "md5", NULL); break; case NID_sha1: return EVP_MD_fetch(NULL, "sha1", NULL); break; #ifdef SHA512_DIGEST_LENGTH case NID_sha224: return EVP_MD_fetch(NULL, "sha224", NULL); break; case NID_sha256: return EVP_MD_fetch(NULL, "sha256", NULL); break; case NID_sha384: return EVP_MD_fetch(NULL, "sha384", NULL); break; case NID_sha512: return EVP_MD_fetch(NULL, "sha512", NULL); break; #endif case NID_ripemd160: return EVP_MD_fetch(NULL, "ripemd160", NULL); break; #ifdef WHIRLPOOL_DIGEST_LENGTH case NID_whirlpool: return EVP_MD_fetch(NULL, "whirlpool", NULL); break; #endif default: croak("Unknown digest hash mode %u", hash_method); break; } } #endif unsigned char* get_message_digest(SV* text_SV, int hash_method) { STRLEN text_length; unsigned char* text; #if OPENSSL_VERSION_NUMBER >= 0x30000000L static unsigned char md[EVP_MAX_MD_SIZE]; #endif text = (unsigned char*) SvPV(text_SV, text_length); switch(hash_method) { case NID_md5: #if OPENSSL_VERSION_NUMBER >= 0x30000000L return EVP_Q_digest(NULL, "MD5", NULL, text, text_length, md, NULL) ? md : NULL; #else return MD5(text, text_length, NULL); #endif break; case NID_sha1: return SHA1(text, text_length, NULL); break; #ifdef SHA512_DIGEST_LENGTH case NID_sha224: return SHA224(text, text_length, NULL); break; case NID_sha256: return SHA256(text, text_length, NULL); break; case NID_sha384: return SHA384(text, text_length, NULL); break; case NID_sha512: return SHA512(text, text_length, NULL); break; #endif case NID_ripemd160: #if OPENSSL_VERSION_NUMBER >= 0x30000000L return EVP_Q_digest(NULL, "RIPEMD160", NULL, text, text_length, md, NULL) ? md : NULL; #else return RIPEMD160(text, text_length, NULL); #endif break; #ifdef WHIRLPOOL_DIGEST_LENGTH case NID_whirlpool: return WHIRLPOOL(text, text_length, NULL); break; #endif default: croak("Unknown digest hash mode %u", hash_method); break; } } SV* cor_bn2sv(const BIGNUM* p_bn) { return p_bn != NULL ? sv_2mortal(newSViv((IV) BN_dup(p_bn))) : &PL_sv_undef; } SV* extractBioString(BIO* p_stringBio) { SV* sv; char* datap; long datasize = 0; CHECK_OPEN_SSL(BIO_flush(p_stringBio) == 1); datasize = BIO_get_mem_data(p_stringBio, &datap); sv = newSVpv(datap, datasize); CHECK_OPEN_SSL(BIO_set_close(p_stringBio, BIO_CLOSE) == 1); BIO_free(p_stringBio); return sv; } EVP_PKEY* _load_rsa_key(SV* p_keyStringSv, EVP_PKEY*(*p_loader)(BIO *, EVP_PKEY**, pem_password_cb*, void*), SV* p_passphaseSv) { STRLEN keyStringLength; char* keyString; UNSIGNED_CHAR *passphase = NULL; EVP_PKEY* rsa; BIO* stringBIO; keyString = SvPV(p_keyStringSv, keyStringLength); if (SvPOK(p_passphaseSv)) { passphase = SvPV_nolen(p_passphaseSv); } CHECK_OPEN_SSL(stringBIO = BIO_new_mem_buf(keyString, keyStringLength)); rsa = p_loader(stringBIO, NULL, NULL, passphase); CHECK_OPEN_SSL(BIO_set_close(stringBIO, BIO_CLOSE) == 1); BIO_free(stringBIO); CHECK_OPEN_SSL(rsa); return rsa; } #if OPENSSL_VERSION_NUMBER >= 0x30000000L SV* rsa_crypt(rsaData* p_rsa, SV* p_from, int (*p_crypt)(EVP_PKEY_CTX*, unsigned char*, size_t*, const unsigned char*, size_t), int (*init_crypt)(EVP_PKEY_CTX*), int public) #else SV* rsa_crypt(rsaData* p_rsa, SV* p_from, int (*p_crypt)(int, const unsigned char*, unsigned char*, RSA*, int)) #endif { STRLEN from_length; SIZE_T_INT to_length; int size; unsigned char* from; UNSIGNED_CHAR *to; SV* sv; from = (unsigned char*) SvPV(p_from, from_length); size = EVP_PKEY_get_size(p_rsa->rsa); CHECK_NEW(to, size, UNSIGNED_CHAR); #if OPENSSL_VERSION_NUMBER >= 0x30000000L EVP_PKEY_CTX *ctx; OSSL_LIB_CTX *ossllibctx = OSSL_LIB_CTX_new(); if (public) { ctx = EVP_PKEY_CTX_new_from_pkey(ossllibctx, (EVP_PKEY* )p_rsa->rsa, NULL); } else { ctx = EVP_PKEY_CTX_new((EVP_PKEY* )p_rsa->rsa, NULL); } CHECK_OPEN_SSL(ctx); CHECK_OPEN_SSL(init_crypt(ctx) == 1); CHECK_OPEN_SSL(EVP_PKEY_CTX_set_rsa_padding(ctx, p_rsa->padding) > 0); CHECK_OPEN_SSL(p_crypt(ctx, NULL, &to_length, from, from_length) == 1); CHECK_OPEN_SSL(p_crypt(ctx, to, &to_length, from, from_length) == 1); EVP_PKEY_CTX_free(ctx); #else to_length = p_crypt( from_length, from, (unsigned char*) to, p_rsa->rsa, p_rsa->padding); #endif if (to_length < 0) { Safefree(to); CHECK_OPEN_SSL(0); } sv = newSVpv((char* ) to, to_length); Safefree(to); return sv; } MODULE = Crypt::OpenSSL::RSA PACKAGE = Crypt::OpenSSL::RSA PROTOTYPES: DISABLE BOOT: #if OPENSSL_VERSION_NUMBER < 0x10100000L # might introduce memory leak without calling EVP_cleanup() on exit # see https://wiki.openssl.org/index.php/Library_Initialization ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); #else # NOOP #endif SV* new_private_key(proto, key_string_SV, passphase_SV=&PL_sv_undef) SV* proto; SV* key_string_SV; SV* passphase_SV; CODE: RETVAL = make_rsa_obj( proto, _load_rsa_key(key_string_SV, PEM_read_bio_PrivateKey, passphase_SV)); OUTPUT: RETVAL SV* _new_public_key_pkcs1(proto, key_string_SV) SV* proto; SV* key_string_SV; CODE: RETVAL = make_rsa_obj( proto, _load_rsa_key(key_string_SV, PEM_read_bio_RSAPublicKey, &PL_sv_undef)); OUTPUT: RETVAL SV* _new_public_key_x509(proto, key_string_SV) SV* proto; SV* key_string_SV; CODE: RETVAL = make_rsa_obj( proto, _load_rsa_key(key_string_SV, PEM_read_bio_RSA_PUBKEY, &PL_sv_undef)); OUTPUT: RETVAL void DESTROY(p_rsa) rsaData* p_rsa; CODE: EVP_PKEY_free(p_rsa->rsa); Safefree(p_rsa); SV* get_private_key_string(p_rsa, passphase_SV=&PL_sv_undef, cipher_name_SV=&PL_sv_undef) rsaData* p_rsa; SV* passphase_SV; SV* cipher_name_SV; PREINIT: BIO* stringBIO; char* passphase = NULL; STRLEN passphaseLength = 0; char* cipher_name; const EVP_CIPHER* enc = NULL; CODE: if (SvPOK(cipher_name_SV) && !SvPOK(passphase_SV)) { croak("Passphrase is required for cipher"); } if (SvPOK(passphase_SV)) { passphase = SvPV(passphase_SV, passphaseLength); if (SvPOK(cipher_name_SV)) { cipher_name = SvPV_nolen(cipher_name_SV); } else { cipher_name = "des3"; } enc = EVP_get_cipherbyname(cipher_name); if (enc == NULL) { croak("Unsupported cipher: %s", cipher_name); } } CHECK_OPEN_SSL(stringBIO = BIO_new(BIO_s_mem())); PEM_write_bio_PrivateKey_traditional( stringBIO, p_rsa->rsa, enc, (unsigned char* ) passphase, passphaseLength, NULL, NULL); RETVAL = extractBioString(stringBIO); OUTPUT: RETVAL SV* get_public_key_string(p_rsa) rsaData* p_rsa; PREINIT: BIO* stringBIO; CODE: CHECK_OPEN_SSL(stringBIO = BIO_new(BIO_s_mem())); #if OPENSSL_VERSION_NUMBER >= 0x30000000L OSSL_ENCODER_CTX *ctx = NULL; ctx = OSSL_ENCODER_CTX_new_for_pkey(p_rsa->rsa, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, "PEM", "PKCS1", NULL); CHECK_OPEN_SSL(ctx != NULL && OSSL_ENCODER_CTX_get_num_encoders(ctx)); CHECK_OPEN_SSL(OSSL_ENCODER_to_bio(ctx, stringBIO) == 1); OSSL_ENCODER_CTX_free(ctx); #else PEM_write_bio_RSAPublicKey(stringBIO, p_rsa->rsa); #endif RETVAL = extractBioString(stringBIO); OUTPUT: RETVAL SV* get_public_key_x509_string(p_rsa) rsaData* p_rsa; PREINIT: BIO* stringBIO; CODE: CHECK_OPEN_SSL(stringBIO = BIO_new(BIO_s_mem())); PEM_write_bio_PUBKEY(stringBIO, p_rsa->rsa); RETVAL = extractBioString(stringBIO); OUTPUT: RETVAL SV* generate_key(proto, bitsSV, exponent = 65537) SV* proto; SV* bitsSV; unsigned long exponent; PREINIT: EVP_PKEY* rsa = NULL; #if OPENSSL_VERSION_NUMBER >= 0x30000000L EVP_PKEY_CTX *ctx; #endif CODE: BIGNUM *e; e = BN_new(); BN_set_word(e, exponent); #if OPENSSL_VERSION_NUMBER < 0x00908000L rsa = RSA_generate_key(SvIV(bitsSV), exponent, NULL, NULL); CHECK_OPEN_SSL(rsa != NULL); #endif #if OPENSSL_VERSION_NUMBER >= 0x00908000L && OPENSSL_VERSION_NUMBER < 0x30000000L rsa = RSA_new(); if (!RSA_generate_key_ex(rsa, SvIV(bitsSV), e, NULL)) croak("Unable to generate a key"); BN_free(e); CHECK_OPEN_SSL(rsa != NULL); #endif #if OPENSSL_VERSION_NUMBER >= 0x30000000L ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); CHECK_OPEN_SSL(ctx); CHECK_OPEN_SSL(EVP_PKEY_keygen_init(ctx) == 1); CHECK_OPEN_SSL(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, SvIV(bitsSV)) > 0); CHECK_OPEN_SSL(EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, e) >0); CHECK_OPEN_SSL(EVP_PKEY_generate(ctx, &rsa) == 1); CHECK_OPEN_SSL(rsa != NULL); e = NULL; BN_free(e); EVP_PKEY_CTX_free(ctx); #endif CHECK_OPEN_SSL(rsa); RETVAL = make_rsa_obj(proto, rsa); OUTPUT: RETVAL SV* _new_key_from_parameters(proto, n, e, d, p, q) SV* proto; BIGNUM* n; BIGNUM* e; BIGNUM* d; BIGNUM* p; BIGNUM* q; PREINIT: EVP_PKEY* rsa = NULL; BN_CTX* ctx = NULL; BIGNUM* p_minus_1 = NULL; BIGNUM* q_minus_1 = NULL; BIGNUM* dmp1 = NULL; BIGNUM* dmq1 = NULL; BIGNUM* iqmp = NULL; int error; CODE: { if (!(n && e)) { croak("At least a modulus and public key must be provided"); } #if OPENSSL_VERSION_NUMBER >= 0x30000000L OSSL_PARAM *params = NULL; EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); CHECK_OPEN_SSL(pctx != NULL); CHECK_OPEN_SSL(EVP_PKEY_fromdata_init(pctx) > 0); OSSL_PARAM_BLD *params_build = OSSL_PARAM_BLD_new(); CHECK_OPEN_SSL(params_build) #else CHECK_OPEN_SSL(rsa = RSA_new()); #endif #if OLD_CRUFTY_SSL_VERSION rsa->n = n; rsa->e = e; #endif #if OPENSSL_VERSION_NUMBER >= 0x30000000L CHECK_OPEN_SSL(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_N, n)); CHECK_OPEN_SSL(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_E, e)); #endif if (p || q) { error = 0; THROW(ctx = BN_CTX_new()); if (!p) { THROW(p = BN_new()); THROW(BN_div(p, NULL, n, q, ctx)); } else if (!q) { q = BN_new(); THROW(BN_div(q, NULL, n, p, ctx)); } #if OLD_CRUFTY_SSL_VERSION rsa->p = p; rsa->q = q; #else #if OPENSSL_VERSION_NUMBER >= 0x30000000L #else THROW(RSA_set0_factors(rsa, p, q)); #endif #endif THROW(p_minus_1 = BN_new()); THROW(BN_sub(p_minus_1, p, BN_value_one())); THROW(q_minus_1 = BN_new()); THROW(BN_sub(q_minus_1, q, BN_value_one())); if (!d) { THROW(d = BN_new()); THROW(BN_mul(d, p_minus_1, q_minus_1, ctx)); THROW(BN_mod_inverse(d, e, d, ctx)); } #if OLD_CRUFTY_SSL_VERSION rsa->d = d; #else #if OPENSSL_VERSION_NUMBER >= 0x30000000L THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_D, d)); THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_FACTOR1, p)); THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_FACTOR2, q)); #else THROW(RSA_set0_key(rsa, n, e, d)); #endif #endif THROW(dmp1 = BN_new()); THROW(BN_mod(dmp1, d, p_minus_1, ctx)); THROW(dmq1 = BN_new()); THROW(BN_mod(dmq1, d, q_minus_1, ctx)); THROW(iqmp = BN_new()); THROW(BN_mod_inverse(iqmp, q, p, ctx)); #if OLD_CRUFTY_SSL_VERSION rsa->dmp1 = dmp1; rsa->dmq1 = dmq1; rsa->iqmp = iqmp; #else #if OPENSSL_VERSION_NUMBER >= 0x30000000L THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_EXPONENT1, dmp1)); THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_EXPONENT2, dmq1)); THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, iqmp)); params = OSSL_PARAM_BLD_to_param(params_build); THROW(params != NULL); int status = EVP_PKEY_fromdata(pctx, &rsa, EVP_PKEY_KEYPAIR, params); THROW( status > 0 && rsa != NULL ); EVP_PKEY_CTX* test_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, rsa, NULL); THROW(EVP_PKEY_check(test_ctx) == 1); #else THROW(RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp)); #endif #endif dmp1 = dmq1 = iqmp = NULL; #if OPENSSL_VERSION_NUMBER >= 0x30000000L OSSL_PARAM_BLD_free(params_build); OSSL_PARAM_free(params); #else THROW(RSA_check_key(rsa) == 1); #endif } else { #if OLD_CRUFTY_SSL_VERSION rsa->d = d; #else #if OPENSSL_VERSION_NUMBER >= 0x30000000L if(d != NULL) THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_D, d)); params = OSSL_PARAM_BLD_to_param(params_build); THROW(params != NULL); int status = EVP_PKEY_fromdata(pctx, &rsa, EVP_PKEY_KEYPAIR, params); THROW( status > 0 && rsa != NULL ); #else CHECK_OPEN_SSL(RSA_set0_key(rsa, n, e, d)); #endif #endif } RETVAL = make_rsa_obj(proto, rsa); if(RETVAL) goto end; err: //if (p) BN_clear_free(p); if (p_minus_1) BN_clear_free(p_minus_1); //if (q) BN_clear_free(q); //if (d) BN_clear_free(d); if (q_minus_1) BN_clear_free(q_minus_1); if (dmp1) BN_clear_free(dmp1); if (dmq1) BN_clear_free(dmq1); if (iqmp) BN_clear_free(iqmp); if (ctx) BN_CTX_free(ctx); if (error) { EVP_PKEY_free(rsa); CHECK_OPEN_SSL(0); } } end: OUTPUT: RETVAL void _get_key_parameters(p_rsa) rsaData* p_rsa; PREINIT: #if OPENSSL_VERSION_NUMBER >= 0x30000000L BIGNUM* n = NULL; BIGNUM* e = NULL; BIGNUM* d = NULL; BIGNUM* p = NULL; BIGNUM* q = NULL; BIGNUM* dmp1 = NULL; BIGNUM* dmq1 = NULL; BIGNUM* iqmp = NULL; #else const BIGNUM* n; const BIGNUM* e; const BIGNUM* d; const BIGNUM* p; const BIGNUM* q; const BIGNUM* dmp1; const BIGNUM* dmq1; const BIGNUM* iqmp; #endif PPCODE: { EVP_PKEY* rsa; rsa = p_rsa->rsa; #if OLD_CRUFTY_SSL_VERSION n = rsa->n; e = rsa->e; d = rsa->d; p = rsa->p; q = rsa->q; dmp1 = rsa->dmp1; dmq1 = rsa->dmq1; iqmp = rsa->iqmp; #else #if OPENSSL_VERSION_NUMBER >= 0x30000000L EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_N, &n); EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_E, &e); EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_D, &d); EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_FACTOR1, &p); EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_FACTOR2, &q); EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_EXPONENT1, &dmp1); EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_EXPONENT2, &dmq1); EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, &iqmp); #else RSA_get0_key(rsa, &n, &e, &d); RSA_get0_factors(rsa, &p, &q); RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); #endif #endif XPUSHs(cor_bn2sv(n)); XPUSHs(cor_bn2sv(e)); XPUSHs(cor_bn2sv(d)); XPUSHs(cor_bn2sv(p)); XPUSHs(cor_bn2sv(q)); XPUSHs(cor_bn2sv(dmp1)); XPUSHs(cor_bn2sv(dmq1)); XPUSHs(cor_bn2sv(iqmp)); } SV* encrypt(p_rsa, p_plaintext) rsaData* p_rsa; SV* p_plaintext; CODE: #if OPENSSL_VERSION_NUMBER >= 0x30000000L RETVAL = rsa_crypt(p_rsa, p_plaintext, EVP_PKEY_encrypt, EVP_PKEY_encrypt_init, 1 /* public */); #else RETVAL = rsa_crypt(p_rsa, p_plaintext, RSA_public_encrypt); #endif OUTPUT: RETVAL SV* decrypt(p_rsa, p_ciphertext) rsaData* p_rsa; SV* p_ciphertext; CODE: if (!_is_private(p_rsa)) { croak("Public keys cannot decrypt"); } #if OPENSSL_VERSION_NUMBER >= 0x30000000L RETVAL = rsa_crypt(p_rsa, p_ciphertext, EVP_PKEY_decrypt, EVP_PKEY_decrypt_init, 0 /* private */); #else RETVAL = rsa_crypt(p_rsa, p_ciphertext, RSA_private_decrypt); #endif OUTPUT: RETVAL SV* private_encrypt(p_rsa, p_plaintext) rsaData* p_rsa; SV* p_plaintext; CODE: if (!_is_private(p_rsa)) { croak("Public keys cannot private_encrypt"); } #if OPENSSL_VERSION_NUMBER >= 0x30000000L RETVAL = rsa_crypt(p_rsa, p_plaintext, EVP_PKEY_sign, EVP_PKEY_sign_init, 0 /* private */); #else RETVAL = rsa_crypt(p_rsa, p_plaintext, RSA_private_encrypt); #endif OUTPUT: RETVAL SV* public_decrypt(p_rsa, p_ciphertext) rsaData* p_rsa; SV* p_ciphertext; CODE: #if OPENSSL_VERSION_NUMBER >= 0x30000000L RETVAL = rsa_crypt(p_rsa, p_ciphertext, EVP_PKEY_verify_recover, EVP_PKEY_verify_recover_init, 1 /*public */); #else RETVAL = rsa_crypt(p_rsa, p_ciphertext, RSA_public_decrypt); #endif OUTPUT: RETVAL int size(p_rsa) rsaData* p_rsa; CODE: RETVAL = EVP_PKEY_get_size(p_rsa->rsa); OUTPUT: RETVAL int check_key(p_rsa) rsaData* p_rsa; CODE: if (!_is_private(p_rsa)) { croak("Public keys cannot be checked"); } #if OPENSSL_VERSION_NUMBER >= 0x30000000L EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_pkey(NULL, p_rsa->rsa, NULL); RETVAL = EVP_PKEY_private_check(pctx); #else RETVAL = RSA_check_key(p_rsa->rsa); #endif OUTPUT: RETVAL # Seed the PRNG with user-provided bytes; returns true if the # seeding was sufficient. int _random_seed(random_bytes_SV) SV* random_bytes_SV; PREINIT: STRLEN random_bytes_length; char* random_bytes; CODE: random_bytes = SvPV(random_bytes_SV, random_bytes_length); RAND_seed(random_bytes, random_bytes_length); RETVAL = RAND_status(); OUTPUT: RETVAL # Returns true if the PRNG has enough seed data int _random_status() CODE: RETVAL = RAND_status(); OUTPUT: RETVAL void use_md5_hash(p_rsa) rsaData* p_rsa; CODE: p_rsa->hashMode = NID_md5; void use_sha1_hash(p_rsa) rsaData* p_rsa; CODE: p_rsa->hashMode = NID_sha1; #ifdef SHA512_DIGEST_LENGTH void use_sha224_hash(p_rsa) rsaData* p_rsa; CODE: p_rsa->hashMode = NID_sha224; void use_sha256_hash(p_rsa) rsaData* p_rsa; CODE: p_rsa->hashMode = NID_sha256; void use_sha384_hash(p_rsa) rsaData* p_rsa; CODE: p_rsa->hashMode = NID_sha384; void use_sha512_hash(p_rsa) rsaData* p_rsa; CODE: p_rsa->hashMode = NID_sha512; #endif void use_ripemd160_hash(p_rsa) rsaData* p_rsa; CODE: p_rsa->hashMode = NID_ripemd160; #ifdef WHIRLPOOL_DIGEST_LENGTH void use_whirlpool_hash(p_rsa) rsaData* p_rsa; CODE: p_rsa->hashMode = NID_whirlpool; #endif void use_no_padding(p_rsa) rsaData* p_rsa; CODE: p_rsa->padding = RSA_NO_PADDING; void use_pkcs1_padding(p_rsa) rsaData* p_rsa; CODE: croak("PKCS#1 1.5 is disabled as it is known to be vulnerable to marvin attacks."); void use_pkcs1_oaep_padding(p_rsa) rsaData* p_rsa; CODE: p_rsa->padding = RSA_PKCS1_OAEP_PADDING; #if OPENSSL_VERSION_NUMBER < 0x30000000L void use_sslv23_padding(p_rsa) rsaData* p_rsa; CODE: p_rsa->padding = RSA_SSLV23_PADDING; #endif # Sign text. Returns the signature. SV* sign(p_rsa, text_SV) rsaData* p_rsa; SV* text_SV; PREINIT: UNSIGNED_CHAR *signature; unsigned char* digest; SIZE_T_UNSIGNED_INT signature_length; CODE: { if (!_is_private(p_rsa)) { croak("Public keys cannot sign messages"); } CHECK_NEW(signature, EVP_PKEY_get_size(p_rsa->rsa), UNSIGNED_CHAR); CHECK_OPEN_SSL(digest = get_message_digest(text_SV, p_rsa->hashMode)); #if OPENSSL_VERSION_NUMBER >= 0x30000000L EVP_PKEY_CTX *ctx; ctx = EVP_PKEY_CTX_new(p_rsa->rsa, NULL /* no engine */); CHECK_OPEN_SSL(ctx); CHECK_OPEN_SSL(EVP_PKEY_sign_init(ctx)); /* FIXME: Issue setting padding in some cases */ EVP_PKEY_CTX_set_rsa_padding(ctx, p_rsa->padding); EVP_MD* md = get_md_bynid(p_rsa->hashMode); CHECK_OPEN_SSL(md != NULL); int md_status; CHECK_OPEN_SSL((md_status = EVP_PKEY_CTX_set_signature_md(ctx, md)) > 0); CHECK_OPEN_SSL(EVP_PKEY_sign(ctx, NULL, &signature_length, digest, get_digest_length(p_rsa->hashMode)) == 1); //signature = OPENSSL_malloc(signature_length); Newx(signature, signature_length, char); CHECK_OPEN_SSL(signature); CHECK_OPEN_SSL(EVP_PKEY_sign(ctx, signature, &signature_length, digest, get_digest_length(p_rsa->hashMode)) == 1); CHECK_OPEN_SSL(signature); #else CHECK_OPEN_SSL(RSA_sign(p_rsa->hashMode, digest, get_digest_length(p_rsa->hashMode), (unsigned char*) signature, &signature_length, p_rsa->rsa)); #endif RETVAL = newSVpvn((const char* )signature, signature_length); Safefree(signature); } OUTPUT: RETVAL # Verify signature. Returns true if correct, false otherwise. void verify(p_rsa, text_SV, sig_SV) rsaData* p_rsa; SV* text_SV; SV* sig_SV; PPCODE: { unsigned char* sig; unsigned char* digest; STRLEN sig_length; sig = (unsigned char*) SvPV(sig_SV, sig_length); if (EVP_PKEY_get_size(p_rsa->rsa) < sig_length) { croak("Signature longer than key"); } CHECK_OPEN_SSL(digest = get_message_digest(text_SV, p_rsa->hashMode)); #if OPENSSL_VERSION_NUMBER >= 0x30000000L EVP_PKEY_CTX *ctx; ctx = EVP_PKEY_CTX_new(p_rsa->rsa, NULL /* no engine */); CHECK_OPEN_SSL(ctx); CHECK_OPEN_SSL(EVP_PKEY_verify_init(ctx) == 1); /* FIXME: Issue setting padding in some cases */ EVP_PKEY_CTX_set_rsa_padding(ctx, p_rsa->padding); EVP_MD* md = get_md_bynid(p_rsa->hashMode); CHECK_OPEN_SSL(md != NULL); int md_status; CHECK_OPEN_SSL((md_status = EVP_PKEY_CTX_set_signature_md(ctx, md)) > 0); switch (EVP_PKEY_verify(ctx, sig, sig_length, digest, get_digest_length(p_rsa->hashMode))) #else switch(RSA_verify(p_rsa->hashMode, digest, get_digest_length(p_rsa->hashMode), sig, sig_length, p_rsa->rsa)) #endif { case 0: ERR_clear_error(); XSRETURN_NO; break; case 1: XSRETURN_YES; break; default: CHECK_OPEN_SSL(0); break; } } int is_private(p_rsa) rsaData* p_rsa; CODE: RETVAL = _is_private(p_rsa); OUTPUT: RETVAL Crypt-OpenSSL-RSA-0.35/t/0000755000000000000000000000000015006707567013424 5ustar rootrootCrypt-OpenSSL-RSA-0.35/t/z_pod-coverage.t0000644000000000000000000000074415005665725016520 0ustar rootroot# -*- perl -*- use strict; use warnings; use Test::More; BEGIN { plan skip_all => 'done_testing requires Test::More 0.88' if Test::More->VERSION < 0.88; } plan skip_all => 'This test is only run for the module author' unless -d '.git' || $ENV{IS_MAINTAINER}; eval "use Test::Pod::Coverage 1.04"; plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@; for ( all_modules() ) { pod_coverage_ok($_) unless /Filter::decrypt/; } done_testing; Crypt-OpenSSL-RSA-0.35/t/bignum.t0000644000000000000000000000653615005665725015102 0ustar rootrootuse strict; use Test::More; use Crypt::OpenSSL::RSA; $INC{'Crypt/OpenSSL/Bignum.pm'} ? plan( tests => 64 ) : plan( skip_all => "Crypt::OpenSSL::Bignum required for bignum tests" ); sub check_datum { my ( $p_expected, $p_actual ) = @_; ok( defined($p_expected) ? $p_actual && $p_expected->equals($p_actual) : !defined($p_actual) ); } sub check_key_parameters # runs 8 tests { my ( $p_rsa, $n, $e, $d, $p, $q, $dmp1, $dmq1, $iqmp ) = @_; my ( $rn, $re, $rd, $rp, $rq, $rdmp1, $rdmq1, $riqmp ) = $p_rsa->get_key_parameters(); check_datum( $n, $rn ); check_datum( $e, $re ); check_datum( $d, $rd ); check_datum( $p, $rp ); check_datum( $q, $rq ); check_datum( $dmp1, $rdmp1 ); check_datum( $dmq1, $rdmq1 ); check_datum( $iqmp, $riqmp ); } { my $ctx = Crypt::OpenSSL::Bignum::CTX->new(); my $one = Crypt::OpenSSL::Bignum->one(); my $p = Crypt::OpenSSL::Bignum->new_from_word(65521); my $q = Crypt::OpenSSL::Bignum->new_from_word(65537); my $e = Crypt::OpenSSL::Bignum->new_from_word(11); my $d = $e->mod_inverse( $p->sub($one)->mul( $q->sub($one), $ctx ), $ctx ); my $n = $p->mul( $q, $ctx ); my $dmp1 = $d->mod( $p->sub($one), $ctx ); my $dmq1 = $d->mod( $q->sub($one), $ctx ); my $iqmp = $q->mod_inverse( $p, $ctx ); my $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters( $n, $e, $d, $p, $q ); ok($rsa); $rsa->use_no_padding(); my $plaintext = pack( 'C*', 100, 100, 100, 12 ); my $ciphertext = Crypt::OpenSSL::Bignum->new_from_bin($plaintext)->mod_exp( $e, $n, $ctx )->to_bin(); check_key_parameters( $rsa, $n, $e, $d, $p, $q, $dmp1, $dmq1, $iqmp ); ok( $rsa->encrypt($plaintext) eq $ciphertext ); ok( $rsa->decrypt($ciphertext) eq $plaintext ); my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key( $rsa->get_public_key_string() ); $rsa_pub->use_no_padding(); ok( $rsa->private_encrypt($ciphertext) eq $plaintext ); ok( $rsa_pub->public_decrypt($plaintext) eq $ciphertext ); my @pub_parameters = $rsa_pub->get_key_parameters(); ok( scalar(@pub_parameters) == 8 ); check_key_parameters( $rsa_pub, $n, $e ); $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters( $n, $e, $d, $p ); check_key_parameters( $rsa, $n, $e, $d, $p, $q, $dmp1, $dmq1, $iqmp ); $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters( $n, $e, $d, undef, $q ); check_key_parameters( $rsa, $n, $e, $d, $p, $q, $dmp1, $dmq1, $iqmp ); $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters( $n, $e ); check_key_parameters( $rsa, $n, $e ); $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters( $n, $e, $d ); check_key_parameters( $rsa, $n, $e, $d ); $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters( $n, $e, undef, $p ); check_key_parameters( $rsa, $n, $e, $d, $p, $q, $dmp1, $dmq1, $iqmp ); eval { Crypt::OpenSSL::RSA->new_key_from_parameters( $n->sub( Crypt::OpenSSL::Bignum->one() ), $e, $d, undef, $q ); }; ok( $@ =~ /OpenSSL error: p not prime/ ); #try again, to make sure the error queue was properly flushed eval { Crypt::OpenSSL::RSA->new_key_from_parameters( $n->sub( Crypt::OpenSSL::Bignum->one() ), $e, $d, undef, $q ); }; ok( $@ =~ /OpenSSL error: p not prime/ ); } Crypt-OpenSSL-RSA-0.35/t/format.t0000644000000000000000000001014315005665725015076 0ustar rootrootuse strict; use Test; use Crypt::OpenSSL::RSA; BEGIN { plan tests => 19 } my $PRIVATE_KEY_STRING = <new_private_key($PRIVATE_KEY_STRING) ); ok( $PRIVATE_KEY_STRING eq $private_key->get_private_key_string() ); ok( $PUBLIC_KEY_PKCS1_STRING eq $private_key->get_public_key_string() ); ok( $PUBLIC_KEY_X509_STRING eq $private_key->get_public_key_x509_string() ); ok( $public_key = Crypt::OpenSSL::RSA->new_public_key($PUBLIC_KEY_PKCS1_STRING) ); ok( $PUBLIC_KEY_PKCS1_STRING eq $public_key->get_public_key_string() ); ok( $PUBLIC_KEY_X509_STRING eq $public_key->get_public_key_x509_string() ); ok( $public_key = Crypt::OpenSSL::RSA->new_public_key($PUBLIC_KEY_X509_STRING) ); ok( $PUBLIC_KEY_PKCS1_STRING eq $public_key->get_public_key_string() ); ok( $PUBLIC_KEY_X509_STRING eq $public_key->get_public_key_x509_string() ); my $passphase = '123456'; ok( $private_key = Crypt::OpenSSL::RSA->new_private_key( $ENCRYPT_PRIVATE_KEY_STRING, $passphase ) ); ok( $DECRYPT_PRIVATE_KEY_STRING eq $private_key->get_private_key_string() ); ok( $private_key = Crypt::OpenSSL::RSA->new_private_key($DECRYPT_PRIVATE_KEY_STRING) ); ok( $private_key2 = Crypt::OpenSSL::RSA->new_private_key( $private_key->get_private_key_string($passphase), $passphase ) ); ok( $DECRYPT_PRIVATE_KEY_STRING eq $private_key2->get_private_key_string() ); ok( $private_key2 = Crypt::OpenSSL::RSA->new_private_key( $private_key->get_private_key_string( $passphase, 'des3' ), $passphase ) ); ok( $DECRYPT_PRIVATE_KEY_STRING eq $private_key2->get_private_key_string() ); ok( $private_key2 = Crypt::OpenSSL::RSA->new_private_key( $private_key->get_private_key_string( $passphase, 'aes-128-cbc' ), $passphase ) ); ok( $DECRYPT_PRIVATE_KEY_STRING eq $private_key2->get_private_key_string() ); Crypt-OpenSSL-RSA-0.35/t/fakelib/0000755000000000000000000000000015006707567015021 5ustar rootrootCrypt-OpenSSL-RSA-0.35/t/fakelib/Crypt/0000755000000000000000000000000015006707567016122 5ustar rootrootCrypt-OpenSSL-RSA-0.35/t/fakelib/Crypt/OpenSSL/0000755000000000000000000000000015006707567017405 5ustar rootrootCrypt-OpenSSL-RSA-0.35/t/fakelib/Crypt/OpenSSL/Bignum.pm0000644000000000000000000000007314261677161021162 0ustar rootrootpackage Crypt::OpenSSL::Bignum; 0; # make require fail Crypt-OpenSSL-RSA-0.35/t/z_kwalitee.t0000644000000000000000000000101515005665725015742 0ustar rootroot# -*- perl -*- use strict; use warnings; use Test::More; use Config; plan skip_all => 'This test is only run for the module author' unless -d '.git' || $ENV{IS_MAINTAINER}; plan skip_all => 'Test::Kwalitee fails with clang -faddress-sanitizer' if $Config{ccflags} =~ /-faddress-sanitizer/; use File::Copy 'cp'; cp( 'MYMETA.yml', 'META.yml' ) if -e 'MYMETA.yml' and !-e 'META.yml'; eval { require Test::Kwalitee; Test::Kwalitee->import; }; plan skip_all => "Test::Kwalitee needed for testing kwalitee" if $@; Crypt-OpenSSL-RSA-0.35/t/z_pod.t0000644000000000000000000000037415005665725014726 0ustar rootroot# -*- perl -*- use Test::More; plan skip_all => 'This test is only run for the module author' unless -d '.git' || $ENV{IS_MAINTAINER}; eval "use Test::Pod 1.00"; plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; all_pod_files_ok(); Crypt-OpenSSL-RSA-0.35/t/z_perl_minimum_version.t0000644000000000000000000000132015005665725020376 0ustar rootroot# -*- perl -*- # Test that our declared minimum Perl version matches our syntax use strict; BEGIN { $| = 1; $^W = 1; } my @MODULES = ( 'Perl::MinimumVersion 1.20', 'Test::MinimumVersion 0.008', ); # Don't run tests during end-user installs use Test::More; unless ( -d '.git' || $ENV{IS_MAINTAINER} ) { plan( skip_all => "Author tests not required for installation" ); } # Load the testing modules foreach my $MODULE (@MODULES) { eval "use $MODULE"; if ($@) { plan( skip_all => "$MODULE not available for testing" ); die "Failed to load required release-testing module $MODULE" if -d '.git' || $ENV{IS_MAINTAINER}; } } all_minimum_version_ok("5.006"); 1; Crypt-OpenSSL-RSA-0.35/t/sig_die.t0000644000000000000000000000034215005665725015211 0ustar rootrootuse strict; use Test::More; use lib 't/fakelib'; my $handler_called; $SIG{__DIE__} = sub { ++$handler_called }; require Crypt::OpenSSL::RSA; plan tests => 1; ok !$handler_called, 'outer $SIG{__DIE__} handler not called'; Crypt-OpenSSL-RSA-0.35/t/z_meta.t0000644000000000000000000000130315005665725015063 0ustar rootroot# -*- perl -*- # Test that our META.yml file matches the current specification. use strict; BEGIN { $| = 1; $^W = 1; } my $MODULE = 'Test::CPAN::Meta 0.12'; # Don't run tests for installs use Test::More; use Config; plan skip_all => 'This test is only run for the module author' unless -d '.git' || $ENV{IS_MAINTAINER}; plan skip_all => 'Test::CPAN::Meta fails with clang -faddress-sanitizer' if $Config{ccflags} =~ /-faddress-sanitizer/; # Load the testing module eval "use $MODULE;"; if ($@) { plan( skip_all => "$MODULE not available for testing" ); die "Failed to load required release-testing module $MODULE 0.12" if -d '.git' || $ENV{IS_MAINTAINER}; } meta_yaml_ok(); Crypt-OpenSSL-RSA-0.35/t/rsa.t0000644000000000000000000001265315006702011014360 0ustar rootrootuse strict; use Test::More; use Crypt::OpenSSL::Random; use Crypt::OpenSSL::RSA; use Crypt::OpenSSL::Guess qw(openssl_version); BEGIN { plan tests => 37 + ( UNIVERSAL::can( "Crypt::OpenSSL::RSA", "use_sha512_hash" ) ? 4 * 5 : 0 ) + ( UNIVERSAL::can( "Crypt::OpenSSL::RSA", "use_whirlpool_hash" ) ? 1 * 5 : 0 ); } sub _Test_Encrypt_And_Decrypt { my ( $p_plaintext_length, $p_rsa, $p_check_private_encrypt ) = @_; my ( $ciphertext, $decoded_text ); my $plaintext = pack( "C${p_plaintext_length}", ( 1, 255, 0, 128, 4, # Make sure these characters work map { int( rand 256 ) } ( 1 .. $p_plaintext_length - 5 ) ) ); ok( $ciphertext = $p_rsa->encrypt($plaintext) ); ok( $decoded_text = $p_rsa->decrypt($ciphertext) ); ok( $decoded_text eq $plaintext ); if ($p_check_private_encrypt) { ok( $ciphertext = $p_rsa->private_encrypt($plaintext) ); ok( $decoded_text = $p_rsa->public_decrypt($ciphertext) ); ok( $decoded_text eq $plaintext ); } } sub _Test_Sign_And_Verify { my ( $plaintext, $rsa, $rsa_pub, $hash ) = @_; my $sig = eval { $rsa->sign($plaintext) }; SKIP: { skip "OpenSSL error: illegal or unsupported padding mode - $hash", 5 if $@ =~ /illegal or unsupported padding mode/i; ok( $rsa_pub->verify( $plaintext, $sig ) ); my $false_sig = unpack "H*", $sig; $false_sig =~ tr/[a-f]/[0a-d]/; ok( !$rsa_pub->verify( $plaintext, pack( "H*", $false_sig ) ) ); ok( !$rsa->verify( $plaintext, pack( "H*", $false_sig ) ) ); my $sig_of_other = $rsa->sign("different"); ok( !$rsa_pub->verify( $plaintext, $sig_of_other ) ); ok( !$rsa->verify( $plaintext, $sig_of_other ) ); } } sub _check_for_croak { my ( $code, $expected ) = @_; eval { &$code() }; ok( $@, "/$expected/" ); } # On platforms without a /dev/random, we need to manually seed. In # real life, the following would stink, but for testing purposes, it # suffices to seed with any old thing, even if it is not actually # random. We'll at least emulate seeding from Crypt::OpenSSL::Random, # which is what we would have to do in "real life", since the private # data used by the OpenSSL random library apparently does not span # across perl XS modules. Crypt::OpenSSL::Random::random_seed("OpenSSL needs at least 32 bytes."); Crypt::OpenSSL::RSA->import_random_seed(); ok( Crypt::OpenSSL::RSA->generate_key(512)->size() * 8 == 512 ); my $rsa = Crypt::OpenSSL::RSA->generate_key(1024); ok( $rsa->size() * 8 == 1024 ); ok( $rsa->check_key() ); $rsa->use_no_padding(); _Test_Encrypt_And_Decrypt( $rsa->size(), $rsa, 1 ); $rsa->use_pkcs1_oaep_padding(); # private_encrypt does not work with pkcs1_oaep_padding _Test_Encrypt_And_Decrypt( $rsa->size() - 42, $rsa, 0 ); #FIXME - use_sslv23_padding seems to fail on decryption. openssl bug? my $private_key_string = $rsa->get_private_key_string(); my $public_key_string = $rsa->get_public_key_string(); ok( $private_key_string and $public_key_string ); 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) ) ); my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($public_key_string); $rsa->use_pkcs1_oaep_padding(); ok( $plaintext eq $rsa->decrypt( $rsa_pub->encrypt($plaintext) ) ); ok( $rsa_priv->is_private() ); ok( !$rsa_pub->is_private() ); _check_for_croak( sub { $rsa_pub->decrypt( $rsa_pub->encrypt($plaintext) ); }, "Public keys cannot decrypt" ); _check_for_croak( sub { $rsa_pub->check_key(); }, "Public keys cannot be checked" ); _check_for_croak( sub { $rsa_pub->private_encrypt("foo"); }, "Public keys cannot private_encrypt" ); _check_for_croak( sub { $rsa_pub->sign("foo"); }, "Public keys cannot sign messages" ); $plaintext .= $plaintext x 5; # check signature algorithms $rsa->use_md5_hash(); $rsa_pub->use_md5_hash(); _Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "md5" ); $rsa->use_sha1_hash(); $rsa_pub->use_sha1_hash(); _Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "sha1" ); if ( UNIVERSAL::can( "Crypt::OpenSSL::RSA", "use_sha512_hash" ) ) { $rsa->use_sha224_hash(); $rsa_pub->use_sha224_hash(); _Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "sha224" ); $rsa->use_sha256_hash(); $rsa_pub->use_sha256_hash(); _Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "sha256" ); $rsa->use_sha384_hash(); $rsa_pub->use_sha384_hash(); _Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "sha384" ); $rsa->use_sha512_hash(); $rsa_pub->use_sha512_hash(); _Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "sha512" ); } my ( $major, $minor, $patch ) = openssl_version(); SKIP: { skip "ripemd160 in legacy provider between 3.02 and 3.07", 5 if $major eq '3.0' && ( $minor ge '2' && $minor le '6' ); $rsa->use_ripemd160_hash(); $rsa_pub->use_ripemd160_hash(); _Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "ripemd160" ); } if ( UNIVERSAL::can( "Crypt::OpenSSL::RSA", "use_whirlpool_hash" ) ) { $rsa->use_whirlpool_hash(); $rsa_pub->use_whirlpool_hash(); _Test_Sign_And_Verify( $plaintext, $rsa, $rsa_pub, "whirlpool" ); } # check subclassing eval { Crypt::OpenSSL::RSA::Subpackage->generate_key(512); }; ok( !$@ ); package Crypt::OpenSSL::RSA::Subpackage; use base qw(Crypt::OpenSSL::RSA); Crypt-OpenSSL-RSA-0.35/LICENSE0000644000000000000000000004740715005121372014161 0ustar rootroot Terms of Perl itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" ---------------------------------------------------------------------------- The General Public License (GPL) Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS ---------------------------------------------------------------------------- The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End Crypt-OpenSSL-RSA-0.35/Changes0000644000000000000000000002063615006702251014444 0ustar rootrootRevision history for Perl extension Crypt::OpenSSL::RSA. 0.35 May 7 2025 - Disable PKCS#1 v1.5 padding. It's not practical to mitigate marvin attacks so we will instead disable this and require alternatives to address the issue. - Resolves #42 - CVE-2024-2467. 0.34 May 5 2025 - Production release. 0.34_03 May 4 2025 - Fix bug in rsa_crypt. Need to pass NULL 0.34_02 May 4 2025 - t/rsa.t needs to tolerate sha1 being disabled on rhel. 0.34_01 May 3 2025 - docs - plaintext = decrypt(cyphertext) - #44 - Fix issue when libz is not linked on AIX - #50 - Correct openssl version may not be found - #52 - Out of memory on openssl 1.1.1w hpux - #47 - Update FSF address and LGPL name in LICENSE - #55 - stop using AutoLoader - #48 - Whirlpool is missing the header - Move github repo to cpan-authors - Fully support openSSL 3.x API 0.33 July 7 2022 - Update for windows github CI - Remove duplicit 'LICENSE' key - Remove EUMM Remove version check - #31 by removing reference to RSA_SSLV23_PADDING (removed from OpenSSL starting from v3.0.0) - support passphase protected private key load - fix 'unsupported encryption' error on old library versions - Clarify croak message for missing passphrase on older cyphers - More structs opaqued in LibreSSL 3.5 - Use a macro for dealing with older SSL lacking macros - more CI fixups. Drop testing for 5.10 and 5.8. Something is broken upstream. 0.32 Wed Sep 8 2021 - Prefix internal bn2sv function so it doesn't collide with Net::SSLeay - Ensure that verify() leaves openssl error stack clean on failure - Fixed broken SEE ALSO links. - prevent outer $SIG{__DIE__} handler from being called during optional require. - omit done_testing since it does not work for older perl versions 0.31 Mon Sep 24 2018 - Remove default of SHA256 for RSA keys. This has caused significant problems with downstream modules and it has always been possible to do $key->use_sha256_hash() 0.30 Tue May 1 2018 - Working windows library detection - Actively testing on appveyor for windows now. - work correctly on LibreSSL 0.29_03 Mon Apr 16 2018 - Add whirlpool hash support. - Crypt::OpenSSL::Random is now required at comnpile-time. - Use the new interface to RSA_generate_key if available - Add library paths to LIBS from Crypt::OpenSSL::Guess 0.29_02 Sun Apr 15 2018 - Add missing require of Config::OpenSSL::Guess 0.29_01 Fri Apr 13 2018 - Adapt to OpenSSL 1.1.0 (dur-randir) - Move issue tracker to github. - Modernization as in Crypt::OpenSSL::Random. - better MSWin32 hints, fixes MSVC libraries, - more meta tests, - prefer hash mode NID_sha256 over NID_sha1 for sign 0.28 Thu Aug 25 2011 - Moritz Onken (PERLER) - RT 56454 - Win32 compatibility patch (kmx@cpan.org) 0.27 Wed Jun 29 2011 - Todd Rinaldo (TODDR) - RT 65947 - Fix RSA.pm break with perl 5.14+ 0.26 Sun Nov 22 2009 11:01:13 - Change subclassing test to generate a 512 bit key in order to work around an odd issue seen on some 64-bit redhat systems. (CPAN bug 45498) 0.25 Sun May 20 2007 12:56:11 - Add a LICENSE file. - Fix a bug (reported by many) in rsa.t - we were incorrectly counting the number of tests in situations where use_sha512_hash was not available. 0.24 Mon Nov 13 2006 08:21:14 - Fix a bug reported by Mark Martinec where encrypt could segfault if called with insufficient data; it now informatively croaks instead. - Fix a bug reported by Mark Martinec where check_key would segfault instead of croaking when called on a public key. - Fix decrypt and private_encrypt to croak instead of segfault when called on a public key. - Add an is_private method. - Silence a few compiler warnings about ignoring return values from certain BIO_* methods. 0.23 Wed Apr 12 2006 00:06:10 - Provide 32 bytes of seeding in tests, up from 19. - Stop relying on implicit includes, which disappeared in the 0.98 release of OpenSSL. - Apply patch from Jim Radford to add support for SHA{224,256,384,512} 0.22 Mon Nov 15 2005 21:13:20 - Add public_decrypt, private_encrypt methods, contributed by Paul G. Weiss - Some changes to help builds on Redhat9 - Remove deprecated methods: * the no-arg new constructor - use new_from_public_key, new_from_private_key or Crypt::OpenSSL::RSA->generate_key instead * load_public_key - use new_from_public_key * load_private_key - use new_from_private_key * generate_key as an instance method - use it as a class constructor method instead. * set_padding_mode - use use_no_padding, use_pkcs1_padding, use_pkcs1_oaep_padding, or use_sslv23_padding instead. * get_padding_mode - Eliminate all(most all) memory leaks. - fix email address - Stop returning true from methods just to indicate success. - Change default public exponent from 65535 to 65537 0.21 Sun Feb 15 2004 21:13:45 - Include t/format.t in the MANIFEST file, so that it is actually included in the distribution. 0.20 Sun Feb 15 2004 15:21:40 - Finally add support for the public key format produced by "openssl rsa -pubout". - Add comment in readme about locating kerberos files on redhat systems 0.19 Sun Apr 27 2003 18:33:48 - Revert back to old declaration style so that we no longer break under perl 5.005 (spotted by Rob Brown ). - Add some needed use statements in legacy.t and rsa.t (patch submitted by Rob Brown). - Fix typo in docs spotted by Daniel Drown - Update copyright dates. 0.18 Sun Feb 23 2003 20:44:35 - Add two new methods, new_key_from_parameters and get_key_parameters, which, working with Crypt::OpenSSL::Bignum, allow working directly with the paramaters of an rsa key. 0.17 Mon Jan 06 2003 22:43:31 - Workaround for gcc 3.2 compile problems: "/usr/include/openssl/des.h:193: parse error before '&' token" (Patch by Rob Brown ) - Deprecate no-arg constructor, load_*_key methods and the instance method generate_key; switch to three constructors: new_public_key, new_private_key and generate_key (as a class method) - Deprecate set_padding_mode method; replace with use_xxx_padding. - move tests into t directory, use Test as a framework 0.16 Tue Jun 11 22:01:45 - Fix bug reported by Rob McMillin which prevented subclassing. 0.15 Fri Jun 07 09:13:12 - Fix two bugs reported by Gordon Lack : use IV, not I32, for pointers, and cast the right-hand, not left-hand, value when doing an assignment from an SV to an HV 0.14 Sun May 19 12:35:21 - Fix bug reported by Charles Jardine : use Safefree, not free, to release memory allocated by New 0.13 Thu Mar 21 00:10:30 - Incorporating patch from Matthias Bauer , which provides signing and verification, as well as uses OpenSSL's internal error reporting system. This patch also fixes a bug with the RSA_NO_PADDING_MODE. Thanks, Matthias! - Deprecate set_padding_mode in favor of use_xxx_padding. - Rather than returning true on success, false on failure, just croak when there are problems. - Plug memory leaks. - Fix my email address (it's cpan.org, not cpan.com) 0.12 Thu Sep 06 22:44:17 - Fixing bug with Crypt::OpenSSL::Random interoperability - Implementing patch from Thomas Linden fixing a keysize bug - Fixing email address in docs. 0.11 Tue Apr 10 22:45:31 - Fixing bug in test.pl. 0.10 Mon Apr 09 18:25:41 - Moving random routines into Crypt::OpenSSL::Random - Use New instead of malloc 0.09 Mon Apr 02 12:27:10 - Typo fix, and always exercise test random_seed in testing. 0.08 Sun Apr 01 23:04:31 - Changing method names to match convention 0.07 Thu Mar 08 3:31:41 2001 - Allow seeding of the PRNG 0.06 Thu Mar 08 12:40:04 2001 - Adding a readme file. 0.05 Mon Feb 26 10:50:43 2001 - Removing signing and verification, due to bizarre bugs 0.04 Fri Feb 23 10:41:33 2001 - Removing Base64 functionality and dependence 0.01 Wed Feb 14 11:21:42 2001 - original version; created by h2xs 1.19 Crypt-OpenSSL-RSA-0.35/MANIFEST.SKIP0000644000000000000000000000012614212452052015036 0ustar rootroot\.perltidyrc cpanfile ^MANIFEST.bak ^Makefile$ ^.github/ ^.git/ ^MYMETA.* ^.gitignore Crypt-OpenSSL-RSA-0.35/README0000644000000000000000000002207514261733564014045 0ustar rootrootNAME Crypt::OpenSSL::RSA - RSA encoding and decoding, using the openSSL libraries SYNOPSIS use Crypt::OpenSSL::Random; use Crypt::OpenSSL::RSA; # not necessary if we have /dev/random: Crypt::OpenSSL::Random::random_seed($good_entropy); Crypt::OpenSSL::RSA->import_random_seed(); $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($key_string); $ciphertext = $rsa->encrypt($plaintext); $rsa_priv = Crypt::OpenSSL::RSA->new_private_key($key_string); $plaintext = $rsa->encrypt($ciphertext); $rsa = Crypt::OpenSSL::RSA->generate_key(1024); # or $rsa = Crypt::OpenSSL::RSA->generate_key(1024, $prime); print "private key is:\n", $rsa->get_private_key_string(); print "public key (in PKCS1 format) is:\n", $rsa->get_public_key_string(); print "public key (in X509 format) is:\n", $rsa->get_public_key_x509_string(); $rsa_priv->use_md5_hash(); # insecure. use_sha256_hash or use_sha1_hash are the default $signature = $rsa_priv->sign($plaintext); print "Signed correctly\n" if ($rsa->verify($plaintext, $signature)); DESCRIPTION "Crypt::OpenSSL::RSA" provides the ability to RSA encrypt strings which are somewhat shorter than the block size of a key. It also allows for decryption, signatures and signature verification. *NOTE*: Many of the methods in this package can croak, so use "eval", or Error.pm's try/catch mechanism to capture errors. Also, while some methods from earlier versions of this package return true on success, this (never documented) behavior is no longer the case. Class Methods new_public_key Create a new "Crypt::OpenSSL::RSA" object by loading a public key in from a string containing Base64/DER-encoding of either the PKCS1 or X.509 representation of the key. The string should include the "-----BEGIN...-----" and "-----END...-----" lines. The padding is set to PKCS1_OAEP, but can be changed with the "use_xxx_padding" methods. new_private_key Create a new "Crypt::OpenSSL::RSA" object by loading a private key in from an string containing the Base64/DER encoding of the PKCS1 representation of the key. The string should include the "-----BEGIN...-----" and "-----END...-----" lines. The padding is set to PKCS1_OAEP, but can be changed with "use_xxx_padding". An optional parameter can be passed for passphase protected private key: passphase The passphase which protects the private key. generate_key Create a new "Crypt::OpenSSL::RSA" object by constructing a private/public key pair. The first (mandatory) argument is the key size, while the second optional argument specifies the public exponent (the default public exponent is 65537). The padding is set to "PKCS1_OAEP", but can be changed with use_xxx_padding methods. new_key_from_parameters Given Crypt::OpenSSL::Bignum objects for n, e, and optionally d, p, and q, where p and q are the prime factors of n, e is the public exponent and d is the private exponent, create a new Crypt::OpenSSL::RSA object using these values. If p and q are provided and d is undef, d is computed. Note that while p and q are not necessary for a private key, their presence will speed up computation. import_random_seed Import a random seed from Crypt::OpenSSL::Random, since the OpenSSL libraries won't allow sharing of random structures across perl XS modules. Instance Methods DESTROY Clean up after ourselves. In particular, erase and free the memory occupied by the RSA key structure. get_public_key_string Return the Base64/DER-encoded PKCS1 representation of the public key. This string has header and footer lines: -----BEGIN RSA PUBLIC KEY------ -----END RSA PUBLIC KEY------ get_public_key_x509_string Return the Base64/DER-encoded representation of the "subject public key", suitable for use in X509 certificates. This string has header and footer lines: -----BEGIN PUBLIC KEY------ -----END PUBLIC KEY------ and is the format that is produced by running "openssl rsa -pubout". get_private_key_string Return the Base64/DER-encoded PKCS1 representation of the private key. This string has header and footer lines: -----BEGIN RSA PRIVATE KEY------ -----END RSA PRIVATE KEY------ 2 optional parameters can be passed for passphase protected private key string: passphase The passphase which protects the private key. cipher name The cipher algorithm used to protect the private key. Default to 'des3'. encrypt Encrypt a binary "string" using the public (portion of the) key. decrypt Decrypt a binary "string". Croaks if the key is public only. private_encrypt Encrypt a binary "string" using the private key. Croaks if the key is public only. public_decrypt Decrypt a binary "string" using the public (portion of the) key. sign Sign a string using the secret (portion of the) key. verify Check the signature on a text. use_no_padding Use raw RSA encryption. This mode should only be used to implement cryptographically sound padding modes in the application code. Encrypting user data directly with RSA is insecure. use_pkcs1_padding Use PKCS #1 v1.5 padding. This currently is the most widely used mode of padding. use_pkcs1_oaep_padding Use "EME-OAEP" padding as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding parameter. This mode of padding is recommended for all new applications. It is the default mode used by "Crypt::OpenSSL::RSA". use_sslv23_padding Use "PKCS #1 v1.5" padding with an SSL-specific modification that denotes that the server is SSL3 capable. Not available since OpenSSL 3. use_md5_hash Use the RFC 1321 MD5 hashing algorithm by Ron Rivest when signing and verifying messages. Note that this is considered insecure. use_sha1_hash Use the RFC 3174 Secure Hashing Algorithm (FIPS 180-1) when signing and verifying messages. This is the default, when use_sha256_hash is not available. use_sha224_hash, use_sha256_hash, use_sha384_hash, use_sha512_hash These FIPS 180-2 hash algorithms, for use when signing and verifying messages, are only available with newer openssl versions (>= 0.9.8). use_sha256_hash is the default hash mode when available. use_ripemd160_hash Dobbertin, Bosselaers and Preneel's RIPEMD hashing algorithm when signing and verifying messages. use_whirlpool_hash Vincent Rijmen und Paulo S. L. M. Barreto ISO/IEC 10118-3:2004 WHIRLPOOL hashing algorithm when signing and verifying messages. size Returns the size, in bytes, of the key. All encrypted text will be of this size, and depending on the padding mode used, the length of the text to be encrypted should be: pkcs1_oaep_padding at most 42 bytes less than this size. pkcs1_padding or sslv23_padding at most 11 bytes less than this size. no_padding exactly this size. check_key This function validates the RSA key, returning a true value if the key is valid, and a false value otherwise. Croaks if the key is public only. get_key_parameters Return "Crypt::OpenSSL::Bignum" objects representing the values of "n", "e", "d", "p", "q", "d mod (p-1)", "d mod (q-1)", and "1/q mod p", where "p" and "q" are the prime factors of "n", "e" is the public exponent and "d" is the private exponent. Some of these values may return as "undef"; only "n" and "e" will be defined for a public key. The "Crypt::OpenSSL::Bignum" module must be installed for this to work. is_private Return true if this is a private key, and false if it is private only. BUGS There is a small memory leak when generating new keys of more than 512 bits. AUTHOR Ian Robertson, "iroberts@cpan.org". For support, please email "perl-openssl-users@lists.sourceforge.net". ACKNOWLEDGEMENTS LICENSE Copyright (c) 2001-2011 Ian Robertson. Crypt::OpenSSL::RSA is free software; you may redistribute it and/or modify it under the same terms as Perl itself. SEE ALSO perl(1), Crypt::OpenSSL::Random, Crypt::OpenSSL::Bignum, rsa(3), RSA_new(3) , RSA_public_encrypt(3) , RSA_size(3) , RSA_generate_key(3) , RSA_check_key(3) Crypt-OpenSSL-RSA-0.35/Makefile.PL0000644000000000000000000000376015005350305015120 0ustar rootrootuse strict; use warnings; use Config; use 5.006; use ExtUtils::MakeMaker 6.48; use Crypt::OpenSSL::Guess qw(openssl_inc_paths openssl_lib_paths openssl_version); my ($major, $minor, $patch) = openssl_version(); print "OpenSSL version: $major.$minor $patch", "\n"; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. my $libs = ' -lssl -lcrypto'; if ( $Config{osname} eq 'aix' ) { $libs = $libs . ' -lz'; } WriteMakefile( 'NAME' => 'Crypt::OpenSSL::RSA', 'AUTHOR' => 'Ian Robertson ', 'VERSION_FROM' => 'RSA.pm', # finds $VERSION 'DISTNAME' => 'Crypt-OpenSSL-RSA', 'ABSTRACT_FROM' => 'RSA.pm', 'MIN_PERL_VERSION' => 5.006, 'PL_FILES' => {}, 'LICENSE' => 'perl', 'PREREQ_PM' => { 'Crypt::OpenSSL::Random' => 0, 'Test::More' => 0, }, 'OBJECT' => 'RSA.o', 'LIBS' => [openssl_lib_paths() . $libs], 'LDDLFLAGS' => openssl_lib_paths() . ' ' . $Config{lddlflags}, 'DEFINE' => '-DPERL5 -DOPENSSL_NO_KRB5', # perl-5.8/gcc-3.2 needs -DPERL5, and redhat9 likes -DOPENSSL_NO_KRB5 'INC' => openssl_inc_paths(), # e.g., '-I/usr/include/other' 'dist' => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, 'clean' => { FILES => 'Crypt-OpenSSL-RSA-*' }, 'META_MERGE' => { recommends => { 'Crypt::OpenSSL::Bignum' => 0, }, configure_requires => { 'Crypt::OpenSSL::Guess' => '0.11', }, build_requires => { 'Test' => 0, # For testing }, resources => { 'license' => 'http://dev.perl.org/licenses/', 'homepage' => 'http://github.com/cpan-authors/Crypt-OpenSSL-RSA', 'bugtracker' => 'https://github.com/cpan-authors/Crypt-OpenSSL-RSA/issues', 'repository' => 'http://github.com/cpan-authors/Crypt-OpenSSL-RSA', } } ); Crypt-OpenSSL-RSA-0.35/typemap0000644000000000000000000000036014261677161014560 0ustar rootrootTYPEMAP BIGNUM* T_PTR rsaData* O_OBJECT INPUT O_OBJECT if (!(SvROK($arg) && sv_derived_from($arg, PACKAGE_NAME))) { croak(\"argument is not a ${type} object\"); } $var = (${type}) SvIV(SvRV($arg)); OUTPUT Crypt-OpenSSL-RSA-0.35/hints/0000755000000000000000000000000015006707567014306 5ustar rootrootCrypt-OpenSSL-RSA-0.35/hints/MSWin32.pl0000644000000000000000000000066214261677161016007 0ustar rootrootuse Config; use Crypt::OpenSSL::Guess 0.11 qw(openssl_lib_paths); if (my $libs = `pkg-config --libs libssl libcrypto 2>nul`) { # strawberry perl has pkg-config $self->{LIBS} = [openssl_lib_paths() . " $libs"]; } else { $self->{LIBS} = [openssl_lib_paths() . '-lssleay32 -llibeay32'] if $Config{cc} =~ /cl/; # msvc with ActivePerl $self->{LIBS} = [openssl_lib_paths() . '-lssl32 -leay32'] if $Config{gccversion}; # gcc } Crypt-OpenSSL-RSA-0.35/MANIFEST0000644000000000000000000000066115006707567014315 0ustar rootrootChanges hints/MSWin32.pl LICENSE Makefile.PL MANIFEST MANIFEST.SKIP README README.md RSA.pm RSA.xs t/bignum.t t/fakelib/Crypt/OpenSSL/Bignum.pm t/format.t t/rsa.t t/sig_die.t t/z_kwalitee.t t/z_meta.t t/z_perl_minimum_version.t t/z_pod-coverage.t t/z_pod.t typemap META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) Crypt-OpenSSL-RSA-0.35/META.yml0000644000000000000000000000170715006707567014437 0ustar rootroot--- abstract: 'RSA encoding and decoding, using the openSSL libraries' author: - 'Ian Robertson ' build_requires: ExtUtils::MakeMaker: '0' Test: '0' configure_requires: Crypt::OpenSSL::Guess: '0.11' ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Crypt-OpenSSL-RSA no_index: directory: - t - inc recommends: Crypt::OpenSSL::Bignum: '0' requires: Crypt::OpenSSL::Random: '0' Test::More: '0' perl: '5.006' resources: bugtracker: https://github.com/cpan-authors/Crypt-OpenSSL-RSA/issues homepage: http://github.com/cpan-authors/Crypt-OpenSSL-RSA license: http://dev.perl.org/licenses/ repository: http://github.com/cpan-authors/Crypt-OpenSSL-RSA version: '0.35' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' Crypt-OpenSSL-RSA-0.35/META.json0000644000000000000000000000303215006707567014600 0ustar rootroot{ "abstract" : "RSA encoding and decoding, using the openSSL libraries", "author" : [ "Ian Robertson " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Crypt-OpenSSL-RSA", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0", "Test" : "0" } }, "configure" : { "requires" : { "Crypt::OpenSSL::Guess" : "0.11", "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "recommends" : { "Crypt::OpenSSL::Bignum" : "0" }, "requires" : { "Crypt::OpenSSL::Random" : "0", "Test::More" : "0", "perl" : "5.006" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/cpan-authors/Crypt-OpenSSL-RSA/issues" }, "homepage" : "http://github.com/cpan-authors/Crypt-OpenSSL-RSA", "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "url" : "http://github.com/cpan-authors/Crypt-OpenSSL-RSA" } }, "version" : "0.35", "x_serialization_backend" : "JSON::PP version 4.07" }