From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

use strict;
require Exporter;
our $VERSION = '2.20.0';
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(genRsaKey);
use Digest::MD5 qw(md5_base64);
sub genRsaKey {
my ( $key_size, $password ) = @_;
my $rsa = Crypt::OpenSSL::RSA->generate_key( $key_size );
my $keys = {
'private' => $rsa->get_private_key_string(),
'public' => $rsa->get_public_key_x509_string(),
'hash' => md5_base64( $rsa->get_public_key_string() ),
};
if ( $password ) {
my $pem = Convert::PEM->new(
Name => 'RSA PRIVATE KEY',
ASN => q(
RSAPrivateKey SEQUENCE {
version INTEGER,
n INTEGER,
e INTEGER,
d INTEGER,
p INTEGER,
q INTEGER,
dp INTEGER,
dq INTEGER,
iqmp INTEGER
}
)
);
$keys->{private} = $pem->encode(
Content => $pem->decode( Content => $keys->{private} ),
Password => $password,
);
}
return $keys;
}
sub genCertKey {
my ( $key_size, $password, $cn ) = @_;
Net::SSLeay::SSLeay_add_ssl_algorithms();
$cn ||= "localhost";
# Generate 2048 bits RSA key
my $key = Net::SSLeay::EVP_PKEY_new();
Net::SSLeay::EVP_PKEY_assign_RSA( $key,
Net::SSLeay::RSA_generate_key( $key_size, 0x10001 ) );
my $cert = Net::SSLeay::X509_new();
# Serial
Net::SSLeay::ASN1_INTEGER_set(
Net::SSLeay::X509_get_serialNumber($cert),
rand( 2**32 ),
);
# Version
Net::SSLeay::X509_set_version( $cert, 2 );
# Make it last 20 years
Net::SSLeay::ASN1_TIME_set( Net::SSLeay::X509_get_notBefore($cert),
time() );
Net::SSLeay::ASN1_TIME_set( Net::SSLeay::X509_get_notAfter($cert),
time() + 20 * 365 * 86400 );
# set subject
my $subj_e = Net::SSLeay::X509_get_subject_name($cert);
my $subj = { commonName => $cn, };
while ( my ( $k, $v ) = each %$subj ) {
# Not everything we get is nice - try with MBSTRING_UTF8 first and if it
# fails try V_ASN1_T61STRING and finally V_ASN1_OCTET_STRING
Net::SSLeay::X509_NAME_add_entry_by_txt( $subj_e, $k, 0x1000, $v, -1,
0 )
or
Net::SSLeay::X509_NAME_add_entry_by_txt( $subj_e, $k, 20, $v, -1, 0 )
or
Net::SSLeay::X509_NAME_add_entry_by_txt( $subj_e, $k, 4, $v, -1, 0 )
or croak( "failed to add entry for $k - "
. Net::SSLeay::ERR_error_string( Net::SSLeay::ERR_get_error() ) );
}
# Set to self-sign
Net::SSLeay::X509_set_pubkey( $cert, $key );
Net::SSLeay::X509_set_issuer_name( $cert,
Net::SSLeay::X509_get_subject_name($cert) );
# Sign with default alg
Net::SSLeay::X509_sign( $cert, $key, 0 );
my $strCert = Net::SSLeay::PEM_get_string_X509($cert);
my $strPrivate;
if ($password) {
my $alg = Net::SSLeay::EVP_get_cipherbyname("AES-256-CBC")
|| Net::SSLeay::EVP_get_cipherbyname("DES-EDE3-CBC");
$strPrivate =
Net::SSLeay::PEM_get_string_PrivateKey( $key, $password, $alg );
}
else {
$strPrivate = Net::SSLeay::PEM_get_string_PrivateKey($key);
}
# Free OpenSSL objects
Net::SSLeay::X509_free($cert);
Net::SSLeay::EVP_PKEY_free($key);
return { private => $strPrivate, public => $strCert, hash => md5_base64 ($strCert) };
}
sub genEcKey {
my ( $curve ) = @_;
require Crypt::PK::ECC;
my $ec_key = Crypt::PK::ECC->new();
$ec_key->generate_key($curve);
my $pubKey = $ec_key->export_key_pem('public');
my $privKey = $ec_key->export_key_pem('private');
return {
private => $privKey,
public => $pubKey,
hash => md5_base64($pubKey),
};
}
1;
__END__
=head1 NAME
=encoding utf8
Lemonldap::NG::Common::Util::Crypto - Crypto utilities for LemonLDAP::NG
=head1 DESCRIPTION
This package contains various cryptography-related functions
=head1 METHODS
=head3 genCertKey($key_len, $password, $cn)
This method generates a RSA private key and a self-signed certificate, and returns a hashref of
=over
=item public: certificate in PEM format, subject is built from given $cn
=item private: private key in PEM format, optionnaly encrypted with supplied password
=item hash: unique identifier for the key
=back
=head3 genEcKey($curve_name)
This method generates an ECDSA key pair and returns a hashref of
=over
=item public: public key in PEM format
=item private: private key in PEM format
=item hash: unique identifier for the key
=back
=head3 genRsaKey($key_len, $password)
This method generates a RSA key pair and returns a hashref of
=over
=item public: public key in PEM format
=item private: private key in PEM format, optionnaly encrypted with supplied password
=item hash: unique identifier for the key
=back
=head1 AUTHORS
=over
=item LemonLDAP::NG team L<http://lemonldap-ng.org/team>
=back
=head1 BUG REPORT
Use OW2 system to report bug or ask for features:
=head1 DOWNLOAD
Lemonldap::NG is available at
=head1 COPYRIGHT AND LICENSE
See COPYING file for details.
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see L<http://www.gnu.org/licenses/>.
=cut