Security Advisories (5)
CVE-2025-40912 (2025-06-11)

CryptX for Perl before version 0.065 contains a dependency that may be susceptible to malformed unicode. CryptX embeds the tomcrypt library. The versions of that library in CryptX before 0.065 may be susceptible to CVE-2019-17362.

CVE-2025-40914 (2025-06-11)

Perl CryptX before version 0.087 contains a dependency that may be susceptible to an integer overflow. CryptX embeds a version of the libtommath library that is susceptible to an integer overflow associated with CVE-2023-36328.

CVE-2026-41564 (2026-04-23)

CryptX versions before 0.088 for Perl do not reseed the Crypt::PK PRNG state after forking. The Crypt::PK::RSA, Crypt::PK::DSA, Crypt::PK::DH, Crypt::PK::ECC, Crypt::PK::Ed25519 and Crypt::PK::X25519 modules seed a per-object PRNG state in their constructors and reuse it without fork detection. A Crypt::PK::* object created before `fork()` shares byte-identical PRNG state with every child process, and any randomized operation they perform can produce identical output, including key generation. Two ECDSA or DSA signatures from different processes are enough to recover the signing private key through nonce-reuse key recovery. This affects preforking services such as the Starman web server, where a Crypt::PK::* object loaded at startup is inherited by every worker process.

CVE-2018-25099 (2018-10-26)

A user can pass anything as the tag into gcm_decrypt_verify() and it will return decrypted plaintext.

CVE-2026-41565 (2026-05-28)

CryptX versions before 0.088_001 for Perl have a stack buffer overflow in four AEAD decrypt_verify helpers. The gcm_decrypt_verify, ccm_decrypt_verify, chacha20poly1305_decrypt_verify and eax_decrypt_verify XS routines copied the caller-supplied authentication tag into a fixed 144-byte stack buffer (MAXBLOCKSIZE) without checking the supplied length. A longer tag overwrites the stack past the buffer. Version 0.088 added the clamp to gcm_decrypt_verify, and 0.088_001 added it to the other three. Any caller of an affected helper that forwards an attacker-controlled tag longer than the buffer can trigger the overflow.

NAME

Crypt::PK::RSA - Public key cryptography based on RSA

SYNOPSIS

### OO interface

#Encryption: Alice
my $pub = Crypt::PK::RSA->new('Bob_pub_rsa1.der');
my $ct = $pub->encrypt("secret message");
#
#Encryption: Bob (received ciphertext $ct)
my $priv = Crypt::PK::RSA->new('Bob_priv_rsa1.der');
my $pt = $priv->decrypt($ct);

#Signature: Alice
my $priv = Crypt::PK::RSA->new('Alice_priv_rsa1.der');
my $sig = $priv->sign_message($message);
#
#Signature: Bob (received $message + $sig)
my $pub = Crypt::PK::RSA->new('Alice_pub_rsa1.der');
$pub->verify_message($sig, $message) or die "ERROR";

#Key generation
my $pk = Crypt::PK::RSA->new();
$pk->generate_key(256, 65537);
my $private_der = $pk->export_key_der('private');
my $public_der = $pk->export_key_der('public');
my $private_pem = $pk->export_key_pem('private');
my $public_pem = $pk->export_key_pem('public');

### Functional interface

#Encryption: Alice
my $ct = rsa_encrypt('Bob_pub_rsa1.der', "secret message");
#Encryption: Bob (received ciphertext $ct)
my $pt = rsa_decrypt('Bob_priv_rsa1.der', $ct);

#Signature: Alice
my $sig = rsa_sign_message('Alice_priv_rsa1.der', $message);
#Signature: Bob (received $message + $sig)
rsa_verify_message('Alice_pub_rsa1.der', $sig, $message) or die "ERROR";

DESCRIPTION

The module provides a full featured RSA implementation.

METHODS

new

my $pk = Crypt::PK::RSA->new();
#or
my $pk = Crypt::PK::RSA->new($priv_or_pub_key_filename);
#or
my $pk = Crypt::PK::RSA->new(\$buffer_containing_priv_or_pub_key);

Support for password protected PEM keys

my $pk = Crypt::PK::RSA->new($priv_pem_key_filename, $password);
#or
my $pk = Crypt::PK::RSA->new(\$buffer_containing_priv_pem_key, $password);

generate_key

Uses Yarrow-based cryptographically strong random number generator seeded with random data taken from /dev/random (UNIX) or CryptGenRandom (Win32).

$pk->generate_key($size, $e);
# $size .. key size: 128-512 bytes (DEFAULT is 256)
# $e ..... exponent: 3, 17, 257 or 65537 (DEFAULT is 65537)

import_key

Loads private or public key in DER or PEM format.

$pk->import_key($priv_or_pub_key_filename);
#or
$pk->import_key(\$buffer_containing_priv_or_pub_key);

Support for password protected PEM keys

$pk->import_key($pem_filename, $password);
#or
$pk->import_key(\$buffer_containing_pem_key, $password);

Loading private or public keys form perl hash:

$pk->import_key($hashref);

# the $hashref is either a key exported via key2hash
$pk->import_key({
  e  => "10001", #public exponent
  d  => "9ED5C3D3F866E06957CA0E9478A273C39BBDA4EEAC5B...", #private exponent
  N  => "D0A5CCCAE03DF9C2F5C4C8C0CE840D62CDE279990DC6...", #modulus
  p  => "D3EF0028FFAB508E2773C659E428A80FB0E9211346B4...", #p factor of N
  q  => "FC07E46B163CAB6A83B8E467D169534B2077DCDEECAE...", #q factor of N
  qP => "88C6D406F833DF73C8B734548E0385261AD51F4187CF...", #1/q mod p CRT param
  dP => "486F142FEF0A1F53269AC43D2EE4D263E2841B60DA36...", #d mod (p - 1) CRT param
  dQ => "4597284B2968B72C4212DB7E8F24360B987B80514DA9...", #d mod (q - 1) CRT param
});

# or a hash with items corresponding to JWK (JSON Web Key)
$pk->import_key({
{
  kty => "RSA",
  n   => "0vx7agoebGcQSuuPiLJXZpt...eZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
  e   => "AQAB",
  d   => "X4cTteJY_gn4FYPsXB8rdXi...FLN5EEaG6RoVH-HLKD9Mdx5ooGURknhnrRwUkC7h5fJLMWbFAKLWY2v7B6NqSzUvx0_YSf",
  p   => "83i-7IvMGXoMXCskv73TKr8...Z27zvoj6pbUQyLPBQxtPnwD20-60eTmD2ujMt5PoMrm8RmNhVWtjjMmMjOpSicFHjXOuVI",
  q   => "3dfOR9cuYq-0S-mkFLzgItg...q3hWeMuG0ouqnb3obLyuqjVZQ1dIrdgTnCdYzBcOW5r37AFXjift_NGiovonzhKpoVVS78",
  dp  => "G4sPXkc6Ya9y8oJW9_ILj4...zi_H7TkS8x5SdX3oE0oiYwxIiemTAu0UOa5pgFGyJ4c8t2VF40XRugKTP8akhFo5tA77Qe",
  dq  => "s9lAH9fggBsoFR8Oac2R_E...T2kGOhvIllTE1efA6huUvMfBcpn8lqW6vzzYY5SSF7pMd_agI3G8IbpBUb0JiraRNUfLhc",
  qi  => "GyM_p6JrXySiz1toFgKbWV...4ypu9bMWx3QJBfm0FoYzUIZEVEcOqwmRN81oDAaaBk0KWGDjJHDdDmFW3AN7I-pux_mHZG",
});

Supported key formats:

# all formats can be loaded from a file
my $pk = Crypt::PK::RSA->new($filename);

# or from a buffer containing the key
my $pk = Crypt::PK::RSA->new(\$buffer_with_key);
  • RSA public keys

    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHlYKg9DeHB3/dY1D9WCyJTnl5
    vEzAXpUOL9tDtdPUl96brIbbdMLooO1hKjsq98kLs1q4vOn/pxvzk0BRwhiu7Vvb
    VUjAn/2HHDDL0U1utqqlMJhaffeLI3HEq5o/lSMFY7sSkZU/E4YX1yqAN0SE7xfK
    B2uzcNq60sMIfp6siQIDAQAB
    -----END PUBLIC KEY-----
  • RSA private keys

    -----BEGIN RSA PRIVATE KEY-----
    MIICXQIBAAKBgQDHlYKg9DeHB3/dY1D9WCyJTnl5vEzAXpUOL9tDtdPUl96brIbb
    dMLooO1hKjsq98kLs1q4vOn/pxvzk0BRwhiu7VvbVUjAn/2HHDDL0U1utqqlMJha
    ffeLI3HEq5o/lSMFY7sSkZU/E4YX1yqAN0SE7xfKB2uzcNq60sMIfp6siQIDAQAB
    AoGBAI5+GgNcGQDYw9uF+t7FwxZM5sGZRJrbbEPyuvL+sDxKKW6voKCyHi4EJzaF
    9jRZMDqgVJcsmUwjPPuMGBHHJ+MI5Zb3L0jbZkyx8u+U5gf88oy9eZmfGOjmHcMB
    oCgzyoLmJETuyADg2onLanuY3jggFb3tq/jimKjO8xM2R6zhAkEA7uXWWyJI9cCN
    zrVt5R5v6oosjZ4r5VILGMqBRLrzfTvH+WDMK6Rl/2MHE+YDeLajzunaM8qY2456
    GTYEXQsIdQJBANXfMEtXocSdPtoVj3ME8Do/0r+ApgTdcDPCwXOzkmkEJW/UFMSn
    b8CYF5G6sZQN9L5z3s2nvi55PaFV8Q0LMUUCQBh9GvIQm6YFbQPpeTBpZFOIgnSp
    6BoDxPtvlryy5U7LF/6qO4OlwIbjYdBaXbS8FCKbujBg7jZjboSzEtNu1BkCQDGT
    w0Yz0jQZn3A+fzpScr2N/fSWheWqz0+wXdfMUKw3YdZCe236wlUK7KvDc1a2xX1A
    ru1NbTCoujikC3TSm2ECQQDKQshchJlZJmFv9vCFQlGCA/EX+4406xvOOiixbPYC
    pIB4Ee2cmvEdAqSaOjrvgs5zvaCCFBO0MecPStCAxUX6
    -----END RSA PRIVATE KEY-----
  • RSA private keys in password protected PEM format

    -----BEGIN RSA PRIVATE KEY-----
    Proc-Type: 4,ENCRYPTED
    DEK-Info: DES-EDE3-CBC,4D697440FF5AEF18
    
    C09H49Gn99o8b8O2r4+Hqao4r3udvC+QSSfsk20sXatyuZSEmbhyqKAB+13NRj+3
    KIsRTqnL9VkeibIGgLHuekOFKAqeSVZ0PmR4bGWEFxUPAYUvg9N9pIa6hGtNZG+y
    TEpOAfFITb1pbHQhp3j8y7qmKc5kY5LrZSFE8WwA24NTG773E07wJgRxKDkXNGOl
    kki6oYArNEps0DdtHFxzgdRg0+yaotXuFJRuC5V4YzKGG/oSRcgYyXKTwCndb3xt
    aHgI2WprQAPg+qOpLABzoi7bEjCqbHWrwkvnAngylbim2Uyvw1e1xKnzlgIHU7pv
    e/J+s00pTItfqW1IpY2mh4C9nkfkfVKBKaAv7jO0s6aPySATqsdlrzv2kpF6Ub4J
    kgaZDOfZ4K3qkyAYVLWcQeDqg4glv9Ah2J05bTm4qrIMmthYnThyQlGvcjUfCMXs
    0t+mEQbsRY7xKt0o6HzzvQlJ+JsFlLORoslAubJX9iLqpEdnlrj1lD9bo6uIClZ5
    5+aoLcAyz1D4OsauuP5i8VFu+Is+QG4SN/vHVuArjkqi3VpLwSAjNDY+KWbq042l
    CqlM2mwm6FIGUZQFxiLHJD7WDmk1xmae++m+XG9CEDTfrUQ5v+l0O6BTrl80XUfU
    w3gzAWbSjz3UK0FpKeABVFPE9fjNP9fTcS6qL5YJWBPflwxCAbVgsBOW4bOMpDGK
    BJDQTeShWn4BlYCe/vgThI9ERdgZhRz4NcFeDgVA/CqQzVqptvz4PSqH46fqUN2n
    4PtJgKE5cASYUBuAjlD71FecSVVM/OTzL1uxYzXBilzvVn2vSHgo9g==
    -----END RSA PRIVATE KEY-----
  • PKCS#8 encoded private keys

    -----BEGIN PRIVATE KEY-----
    MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANPN17xW4EkH5PXG
    1i/i3rE1EXFcCHyxmz95VRBDs1p3MuYf9mxntbfYAmuzS3KrRWh3IyX/Eh80N/v9
    OXPlwZbVqSTX+L3pCEJtRtsWn0zmswGThjMZiwle0oWuap63L35F1QN8EDaSPSBC
    yGELNRr6rwVYq0w5b+LOcaCZ+/H1AgMBAAECgYEApfu3aGpww+rC3HUhX0+ckyTy
    cXLdV9LbxidwqRlVEb0+DyfXNucjelp2sy5EHy3na9GJovo8mmWSxhCRGKliRkQ6
    XgrEMZdCSaWI2AazuHAGlUJRFEVkvdla3AuBAn6y0YdDp/3kbg0yahmKyD8Gq74z
    nUYbDL3R5JtR2Ad/KlUCQQDvSEICTHbO/BF7hVmlKRYZSNHKEPrv8X/OlppS14Kv
    QRwc+CZ5+l6T1Y+l5cHJQUXrXZoWS1K741TXdUhjjUd7AkEA4pod804Ex8sttdWi
    pHMfeyj+IbPAk5XnBc91jT7AYIeL8ccjtfl99xhMsGFaxrh3wA/4SGEvwzWkbxcq
    H8G5TwJAKNG+0P2SVwURRm0dOdukdXPCtiHnbP9Zujhe4zr4hEUrMpXymmRntfh8
    pORpBpgoAVraams3Fe5WDttnGfSD+QJAOOC6V9HjfUrQhG3FT0XeRwm5EDiQQ/tC
    a8DxHqz7mL8tL1ju68ReC+G7jiJBqNOwqzLW/UP3uyYByiikWChGHQJAHUau7jIM
    45ErO096n94Vh95p76ANxOroWszOt39TyvJOykIfoPwFagLrBWV9Jjos2/D54KE+
    fyoy4t3yHT+/nw==
    -----END PRIVATE KEY-----
  • PKCS#8 encrypted private keys ARE NOT SUPPORTED YET!

    -----BEGIN ENCRYPTED PRIVATE KEY-----
    MIICojAcBgoqhkiG9w0BDAEDMA4ECCQk+Rr1yzzcAgIIAASCAoD/mgpUFjxxM/Ty
    Yt+NeT0Fo4echgoGksqs6+rYhO16oshG664emZfkuNoFGGzJ38X6GVuqIXhlPnYQ
    biKvL37dN/KnoGytFHq9Wnk8dDwjGHPtwajhW5WuIV3NuhW/AO1PF/cRZKFjWrPt
    NWY5CrpfH6t6zojoe+5uyXpH29lQy4OqvSRdPIt/12UcB+tzV7XzSWEuXh8HAi8a
    sYUu6tuCFnq4GrD2ffM4KWFmL5GqBAwN6m0KkyrNni9XT+RaA6zEhv/lVcwg2esa
    4/EzRs0ixzzZDKaml8oCMl9RHtFAbQmdlfV7Ip4rGK9BwY6UFiDMIVru6HynOVQK
    vvZ+j//bgO+3ubrv7psX+vC9Fy/MoH2Tc7MIwDN/QVTciPZlzjWBnBNxMfeFKtEn
    d7NFiapgfLuRQIiDTMrW/clcqvO54NphxhrcgUEoxos4twKZARntqPZHtf8nEM2x
    2sEF5kI65aEF/5Yy16qvP0vZAA2B1kcIdXZ8XLZCp4c3olhkIrmgUpo1gyFXdCoC
    7dT5Cz7/YLkq5hkcFrtp4V9BZMR24fSttc4p24N5xuZ+JneGnGkLX6B+nJAtm9vw
    bZA6P+23GI0qeMzL3HJXwCOTSsWfm/H9W5+2Zmw851aAmE+pZLni/pk3e3iNSWgs
    946x/doA5O0uCFsU7oxme+WAIp2SjhxGoe808Lf1CCFMPboFi1O/E0NsX8SIEX+i
    U+UHi4kxZqVkr3Q5SB/9kiSv8K1bE787yueQOT/dsTYYaMsjAbkEZo0o/47F32T6
    A2ioXHOV/pr5zNHqE5tL+qKEcLYbAUF1O+WvmdqYz+vHQjRQBatAqTmncvLDYr/j
    1HPwZX2d
    -----END ENCRYPTED PRIVATE KEY-----
  • SSH public RSA keys

    ssh-rsa AAAAB3NzaC1yc2EAAAADAQA...6mdYs5iJNGu/ltUdc=
  • SSH public RSA keys (RFC-4716 format)

    ---- BEGIN SSH2 PUBLIC KEY ----
    Comment: "768-bit RSA, converted from OpenSSH"
    AAAAB3NzaC1yc2EAAAADAQABAAAAYQDYebeGQFCnlQiNRE7r9UEbjr+DQMTdw1ZHGB2w6x
    D/DzKem8761GdCpqsLrGaw2D7aSIoP1B5Sz870YoVWHn6Ao7Hvm17V3Kxfn4B01GNQTM5+
    L26mdYs5iJNGu/ltUdc=
    ---- END SSH2 PUBLIC KEY ----
  • RSA private keys in JSON Web Key (JWK) format

    See http://tools.ietf.org/html/draft-ietf-jose-json-web-key

    {
      "kty":"RSA",
      "n":"0vx7agoebGcQSuuPiLJXZpt...eZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
      "e":"AQAB",
      "d":"X4cTteJY_gn4FYPsXB8rdXi...FLN5EEaG6RoVH-HLKD9Mdx5ooGURknhnrRwUkC7h5fJLMWbFAKLWY2v7B6NqSzUvx0_YSf",
      "p":"83i-7IvMGXoMXCskv73TKr8...Z27zvoj6pbUQyLPBQxtPnwD20-60eTmD2ujMt5PoMrm8RmNhVWtjjMmMjOpSicFHjXOuVI",
      "q":"3dfOR9cuYq-0S-mkFLzgItg...q3hWeMuG0ouqnb3obLyuqjVZQ1dIrdgTnCdYzBcOW5r37AFXjift_NGiovonzhKpoVVS78",
      "dp":"G4sPXkc6Ya9y8oJW9_ILj4...zi_H7TkS8x5SdX3oE0oiYwxIiemTAu0UOa5pgFGyJ4c8t2VF40XRugKTP8akhFo5tA77Qe",
      "dq":"s9lAH9fggBsoFR8Oac2R_E...T2kGOhvIllTE1efA6huUvMfBcpn8lqW6vzzYY5SSF7pMd_agI3G8IbpBUb0JiraRNUfLhc",
      "qi":"GyM_p6JrXySiz1toFgKbWV...4ypu9bMWx3QJBfm0FoYzUIZEVEcOqwmRN81oDAaaBk0KWGDjJHDdDmFW3AN7I-pux_mHZG",
    }

    BEWARE: For JWK support you need to have JSON::PP, JSON::XS or Cpanel::JSON::XS module.

  • RSA public keys in JSON Web Key (JWK) format

    {
      "kty":"RSA",
      "n": "0vx7agoebGcQSuuPiLJXZp...tN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECP",
      "e":"AQAB",
    }

    BEWARE: For JWK support you need to have JSON::PP, JSON::XS or Cpanel::JSON::XS module.

export_key_der

my $private_der = $pk->export_key_der('private');
#or
my $public_der = $pk->export_key_der('public');

export_key_pem

my $private_pem = $pk->export_key_pem('private');
#or
my $public_pem = $pk->export_key_pem('public');
#or
my $public_pem = $pk->export_key_pem('public_x509');

With parameter 'public' uses header and footer lines:

-----BEGIN RSA PUBLIC KEY------
-----END RSA PUBLIC KEY------

With parameter 'public_x509' uses header and footer lines:

-----BEGIN PUBLIC KEY------
-----END PUBLIC KEY------

Support for password protected PEM keys

my $private_pem = $pk->export_key_pem('private', $password);
#or
my $private_pem = $pk->export_key_pem('private', $password, $cipher);

# supported ciphers: 'DES-CBC'
#                    'DES-EDE3-CBC'
#                    'SEED-CBC'
#                    'CAMELLIA-128-CBC'
#                    'CAMELLIA-192-CBC'
#                    'CAMELLIA-256-CBC'
#                    'AES-128-CBC'
#                    'AES-192-CBC'
#                    'AES-256-CBC' (DEFAULT)

export_key_jwk

Exports public/private keys as a JSON Web Key (JWK).

my $private_json_text = $pk->export_key_jwk('private');
#or
my $public_json_text = $pk->export_key_jwk('public');

Also exports public/private keys as a perl HASH with JWK structure.

my $jwk_hash = $pk->export_key_jwk('private', 1);
#or
my $jwk_hash = $pk->export_key_jwk('public', 1);

BEWARE: For JWK support you need to have JSON::PP, JSON::XS or Cpanel::JSON::XS module.

encrypt

my $pk = Crypt::PK::RSA->new($pub_key_filename);
my $ct = $pk->encrypt($message);
#or
my $ct = $pk->encrypt($message, $padding);
#or
my $ct = $pk->encrypt($message, 'oaep', $hash_name, $lparam);

# $padding .................... 'oaep' (DEFAULT), 'v1.5' or 'none'
# $hash_name (only for oaep) .. 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
# $lparam (only for oaep) ..... DEFAULT is empty string

decrypt

my $pk = Crypt::PK::RSA->new($priv_key_filename);
my $pt = $pk->decrypt($ciphertext);
#or
my $pt = $pk->decrypt($ciphertext, $padding);
#or
my $pt = $pk->decrypt($ciphertext, 'oaep', $hash_name, $lparam);

# $padding .................... 'oaep' (DEFAULT), 'v1.5' or 'none'
# $hash_name (only for oaep) .. 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
# $lparam (only for oaep) ..... DEFAULT is empty string

sign_message

my $pk = Crypt::PK::RSA->new($priv_key_filename);
my $signature = $priv->sign_message($message);
#or
my $signature = $priv->sign_message($message, $hash_name);
#or
my $signature = $priv->sign_message($message, $hash_name, $padding);
#or
my $signature = $priv->sign_message($message, $hash_name, 'pss', $saltlen);

# $hash_name ............... 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
# $padding ................. 'pss' (DEFAULT) or 'v1.5'
# $saltlen (only for pss) .. DEFAULT is 12

verify_message

my $pk = Crypt::PK::RSA->new($pub_key_filename);
my $valid = $pub->verify_message($signature, $message);
#or
my $valid = $pub->verify_message($signature, $message, $hash_name);
#or
my $valid = $pub->verify_message($signature, $message, $hash_name, $padding);
#or
my $valid = $pub->verify_message($signature, $message, $hash_name, 'pss', $saltlen);

# $hash_name ............... 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
# $padding ................. 'pss' (DEFAULT) or 'v1.5'
# $saltlen (only for pss) .. DEFAULT is 12

sign_hash

my $pk = Crypt::PK::RSA->new($priv_key_filename);
my $signature = $priv->sign_hash($message_hash);
#or
my $signature = $priv->sign_hash($message_hash, $hash_name);
#or
my $signature = $priv->sign_hash($message_hash, $hash_name, $padding);
#or
my $signature = $priv->sign_hash($message_hash, $hash_name, 'pss', $saltlen);

# $hash_name ............... 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
# $padding ................. 'pss' (DEFAULT) or 'v1.5'
# $saltlen (only for pss) .. DEFAULT is 12

verify_hash

my $pk = Crypt::PK::RSA->new($pub_key_filename);
my $valid = $pub->verify_hash($signature, $message_hash);
#or
my $valid = $pub->verify_hash($signature, $message_hash, $hash_name);
#or
my $valid = $pub->verify_hash($signature, $message_hash, $hash_name, $padding);
#or
my $valid = $pub->verify_hash($signature, $message_hash, $hash_name, 'pss', $saltlen);

# $hash_name ............... 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
# $padding ................. 'pss' (DEFAULT) or 'v1.5'
# $saltlen (only for pss) .. DEFAULT is 12

is_private

my $rv = $pk->is_private;
# 1 .. private key loaded
# 0 .. public key loaded
# undef .. no key loaded

size

my $size = $pk->size;
# returns key size in bytes or undef if no key loaded

key2hash

my $hash = $pk->key2hash;

# returns hash like this (or undef if no key loaded):
{
  type => 1,   # integer: 1 .. private, 0 .. public
  size => 256, # integer: key size in bytes
  # all the rest are hex strings
  e  => "10001", #public exponent
  d  => "9ED5C3D3F866E06957CA0E9478A273C39BBDA4EEAC5B...", #private exponent
  N  => "D0A5CCCAE03DF9C2F5C4C8C0CE840D62CDE279990DC6...", #modulus
  p  => "D3EF0028FFAB508E2773C659E428A80FB0E9211346B4...", #p factor of N
  q  => "FC07E46B163CAB6A83B8E467D169534B2077DCDEECAE...", #q factor of N
  qP => "88C6D406F833DF73C8B734548E0385261AD51F4187CF...", #1/q mod p CRT param
  dP => "486F142FEF0A1F53269AC43D2EE4D263E2841B60DA36...", #d mod (p - 1) CRT param
  dQ => "4597284B2968B72C4212DB7E8F24360B987B80514DA9...", #d mod (q - 1) CRT param
}

FUNCTIONS

rsa_encrypt

RSA based encryption. See method "encrypt" below.

my $ct = rsa_encrypt($pub_key_filename, $message);
#or
my $ct = rsa_encrypt(\$buffer_containing_pub_key, $message);
#or
my $ct = rsa_encrypt($pub_key, $message, $padding);
#or
my $ct = rsa_encrypt($pub_key, $message, 'oaep', $hash_name, $lparam);

# $padding .................... 'oaep' (DEFAULT), 'v1.5' or 'none'
# $hash_name (only for oaep) .. 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
# $lparam (only for oaep) ..... DEFAULT is empty string

rsa_decrypt

RSA based decryption. See method "decrypt" below.

my $pt = rsa_decrypt($priv_key_filename, $ciphertext);
#or
my $pt = rsa_decrypt(\$buffer_containing_priv_key, $ciphertext);
#or
my $pt = rsa_decrypt($priv_key, $ciphertext, $padding);
#or
my $pt = rsa_decrypt($priv_key, $ciphertext, 'oaep', $hash_name, $lparam);

# $padding .................... 'oaep' (DEFAULT), 'v1.5' or 'none'
# $hash_name (only for oaep) .. 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
# $lparam (only for oaep) ..... DEFAULT is empty string

rsa_sign_message

Generate RSA signature. See method "sign_message" below.

my $sig = rsa_sign_message($priv_key_filename, $message);
#or
my $sig = rsa_sign_message(\$buffer_containing_priv_key, $message);
#or
my $sig = rsa_sign_message($priv_key, $message, $hash_name);
#or
my $sig = rsa_sign_message($priv_key, $message, $hash_name, $padding);
#or
my $sig = rsa_sign_message($priv_key, $message, $hash_name, 'pss', $saltlen);

# $hash_name ............... 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
# $padding ................. 'pss' (DEFAULT) or 'v1.5'
# $saltlen (only for pss) .. DEFAULT is 12

rsa_verify_message

Verify RSA signature. See method "verify_message" below.

rsa_verify_message($pub_key_filename, $signature, $message) or die "ERROR";
#or
rsa_verify_message(\$buffer_containing_pub_key, $signature, $message) or die "ERROR";
#or
rsa_verify_message($pub_key, $signature, $message, $hash_name) or die "ERROR";
#or
rsa_verify_message($pub_key, $signature, $message, $hash_name, $padding) or die "ERROR";
#or
rsa_verify_message($pub_key, $signature, $message, $hash_name, 'pss', $saltlen) or die "ERROR";

# $hash_name ............... 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
# $padding ................. 'pss' (DEFAULT) or 'v1.5'
# $saltlen (only for pss) .. DEFAULT is 12

rsa_sign_hash

Generate RSA signature. See method "sign_hash" below.

my $sig = rsa_sign_hash($priv_key_filename, $message_hash);
#or
my $sig = rsa_sign_hash(\$buffer_containing_priv_key, $message_hash);
#or
my $sig = rsa_sign_hash($priv_key, $message_hash, $hash_name);
#or
my $sig = rsa_sign_hash($priv_key, $message_hash, $hash_name, $padding);
#or
my $sig = rsa_sign_hash($priv_key, $message_hash, $hash_name, 'pss', $saltlen);

# $hash_name ............... 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
# $padding ................. 'pss' (DEFAULT) or 'v1.5'
# $saltlen (only for pss) .. DEFAULT is 12

rsa_verify_hash

Verify RSA signature. See method "verify_hash" below.

rsa_verify_hash($pub_key_filename, $signature, $message_hash) or die "ERROR";
#or
rsa_verify_hash(\$buffer_containing_pub_key, $signature, $message_hash) or die "ERROR";
#or
rsa_verify_hash($pub_key, $signature, $message_hash, $hash_name) or die "ERROR";
#or
rsa_verify_hash($pub_key, $signature, $message_hash, $hash_name, $padding) or die "ERROR";
#or
rsa_verify_hash($pub_key, $signature, $message_hash, $hash_name, 'pss', $saltlen) or die "ERROR";

# $hash_name ............... 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
# $padding ................. 'pss' (DEFAULT) or 'v1.5'
# $saltlen (only for pss) .. DEFAULT is 12

OpenSSL interoperability

### let's have:
# RSA private key in PEM format - rsakey.priv.pem
# RSA public key in PEM format  - rsakey.pub.pem
# data file to be signed or encrypted - input.data

Encrypt by OpenSSL, decrypt by Crypt::PK::RSA

Create encrypted file (from commandline):

openssl rsautl -encrypt -inkey rsakey.pub.pem -pubin -out input.encrypted.rsa -in input.data

Decrypt file (Perl code):

use Crypt::PK::RSA;
use File::Slurp 'read_file';

my $pkrsa = Crypt::PK::RSA->new("rsakey.priv.pem");
my $encfile = read_file("input.encrypted.rsa", binmode=>':raw');
my $plaintext = $pkrsa->decrypt($encfile, 'v1.5');
print $plaintext;

Encrypt by Crypt::PK::RSA, decrypt by OpenSSL

Create encrypted file (Perl code):

use Crypt::PK::RSA;
use File::Slurp 'write_file';

my $plaintext = 'secret message';
my $pkrsa = Crypt::PK::RSA->new("rsakey.pub.pem");
my $encrypted = $pkrsa->encrypt($plaintext, 'v1.5');
write_file("input.encrypted.rsa", {binmode=>':raw'}, $encrypted);

Decrypt file (from commandline):

openssl rsautl -decrypt -inkey rsakey.priv.pem -in input.encrypted.rsa

Sign by OpenSSL, verify by Crypt::PK::RSA

Create signature (from commandline):

openssl dgst -sha1 -sign rsakey.priv.pem -out input.sha1-rsa.sig input.data

Verify signature (Perl code):

use Crypt::PK::RSA;
use Crypt::Digest 'digest_file';
use File::Slurp 'read_file';

my $pkrsa = Crypt::PK::RSA->new("rsakey.pub.pem");
my $signature = read_file("input.sha1-rsa.sig", binmode=>':raw');
my $valid = $pkrsa->verify_hash($signature, digest_file("SHA1", "input.data"), "SHA1", "v1.5");
print $valid ? "SUCCESS" : "FAILURE";

Sign by Crypt::PK::RSA, verify by OpenSSL

Create signature (Perl code):

use Crypt::PK::RSA;
use Crypt::Digest 'digest_file';
use File::Slurp 'write_file';

my $pkrsa = Crypt::PK::RSA->new("rsakey.priv.pem");
my $signature = $pkrsa->sign_hash(digest_file("SHA1", "input.data"), "SHA1", "v1.5");
write_file("input.sha1-rsa.sig", {binmode=>':raw'}, $signature);

Verify signature (from commandline):

openssl dgst -sha1 -verify rsakey.pub.pem -signature input.sha1-rsa.sig input.data

Keys generated by Crypt::PK::RSA

Generate keys (Perl code):

use Crypt::PK::RSA;
use File::Slurp 'write_file';

my $pkrsa = Crypt::PK::RSA->new;
$pkrsa->generate_key(256, 65537);
write_file("rsakey.pub.der",  {binmode=>':raw'}, $pkrsa->export_key_der('public'));
write_file("rsakey.priv.der", {binmode=>':raw'}, $pkrsa->export_key_der('private'));
write_file("rsakey.pub.pem",  $pkrsa->export_key_pem('public_x509'));
write_file("rsakey.priv.pem", $pkrsa->export_key_pem('private'));
write_file("rsakey-passwd.priv.pem", $pkrsa->export_key_pem('private', 'secret'));

Use keys by OpenSSL:

openssl rsa -in rsakey.priv.der -text -inform der
openssl rsa -in rsakey.priv.pem -text
openssl rsa -in rsakey-passwd.priv.pem -text -inform pem -passin pass:secret
openssl rsa -in rsakey.pub.der -pubin -text -inform der
openssl rsa -in rsakey.pub.pem -pubin -text

Keys generated by OpenSSL

Generate keys:

openssl genrsa -out rsakey.priv.pem 1024
openssl rsa -in rsakey.priv.pem -out rsakey.priv.der -outform der
openssl rsa -in rsakey.priv.pem -out rsakey.pub.pem -pubout
openssl rsa -in rsakey.priv.pem -out rsakey.pub.der -outform der -pubout
openssl rsa -in rsakey.priv.pem -passout pass:secret -des3 -out rsakey-passwd.priv.pem

Load keys (Perl code):

use Crypt::PK::RSA;
use File::Slurp 'write_file';

my $pkrsa = Crypt::PK::RSA->new;
$pkrsa->import_key("rsakey.pub.der");
$pkrsa->import_key("rsakey.priv.der");
$pkrsa->import_key("rsakey.pub.pem");
$pkrsa->import_key("rsakey.priv.pem");
$pkrsa->import_key("rsakey-passwd.priv.pem", "secret");

SEE ALSO