kryptos/rsa
RSA (Rivest-Shamir-Adleman) cryptography.
This module provides RSA key generation, signing, and encryption operations. RSA keys can be used for both digital signatures and encryption.
Key Generation
import kryptos/rsa
let assert Ok(#(private_key, public_key)) = rsa.generate_key_pair(2048)
Signing (RSA-PSS)
import kryptos/rsa
import kryptos/hash
let assert Ok(#(private_key, public_key)) = rsa.generate_key_pair(2048)
let message = <<"hello world":utf8>>
let padding = rsa.Pss(rsa.SaltLengthHashLen)
let signature = rsa.sign(private_key, message, hash.Sha256, padding)
let valid = rsa.verify(public_key, message, signature, hash.Sha256, padding)
Encryption (RSA-OAEP)
import kryptos/rsa
import kryptos/hash
let assert Ok(#(private_key, public_key)) = rsa.generate_key_pair(2048)
let plaintext = <<"secret":utf8>>
let padding = rsa.Oaep(hash: hash.Sha256, label: <<>>)
let assert Ok(ciphertext) = rsa.encrypt(public_key, plaintext, padding)
let assert Ok(decrypted) = rsa.decrypt(private_key, ciphertext, padding)
Types
Padding scheme for RSA encryption.
pub type EncryptPadding {
EncryptPkcs1v15
Oaep(hash: hash.HashAlgorithm, label: BitArray)
}
Constructors
-
EncryptPkcs1v15PKCS#1 v1.5 encryption padding.
Warning: Vulnerable to padding oracle attacks. Prefer OAEP for new applications.
JavaScript target: Decryption may fail on Node.js 20.x due to CVE-2023-46809 which disables PKCS#1 v1.5 decryption to prevent the Marvin timing attack. Use Node.js 22+ or OAEP padding instead.
-
Oaep(hash: hash.HashAlgorithm, label: BitArray)RSA-OAEP (Optimal Asymmetric Encryption Padding).
The hash algorithm is used for both OAEP and MGF1. The label is optional associated data (usually empty).
An RSA private key.
pub type PrivateKey
Format for encoding/decoding RSA private keys.
pub type PrivateKeyFormat {
Pkcs8
Pkcs1
}
Constructors
-
Pkcs8PKCS#8 format (PrivateKeyInfo) - works with all key types.
-
Pkcs1PKCS#1 format (RSAPrivateKey) - RSA-specific.
Salt length options for RSA-PSS signatures.
pub type PssSaltLength {
SaltLengthHashLen
SaltLengthMax
SaltLengthExplicit(Int)
}
Constructors
-
SaltLengthHashLenSalt length equals hash output length (recommended).
-
SaltLengthMaxMaximum salt length for the key and hash combination.
-
SaltLengthExplicit(Int)Explicit salt length in bytes.
Format for encoding/decoding RSA public keys.
pub type PublicKeyFormat {
Spki
RsaPublicKey
}
Constructors
-
SpkiSPKI format (SubjectPublicKeyInfo) - works with all key types.
-
RsaPublicKeyPKCS#1 format (RSAPublicKey) - RSA-specific.
Padding scheme for RSA signatures.
pub type SignPadding {
Pkcs1v15
Pss(PssSaltLength)
}
Constructors
-
Pkcs1v15PKCS#1 v1.5 signature padding.
-
Pss(PssSaltLength)RSA-PSS (Probabilistic Signature Scheme) padding.
Values
pub fn coefficient(key: PrivateKey) -> BitArray
Returns the CRT coefficient (qi = q^-1 mod p) as big-endian bytes.
This is part of the CRT (Chinese Remainder Theorem) parameters used for efficient RSA operations.
Parameters
key: The private key
Returns
The CRT coefficient as raw bytes.
pub fn decrypt(
private_key: PrivateKey,
ciphertext: BitArray,
padding: EncryptPadding,
) -> Result(BitArray, Nil)
Decrypts data using RSA with the specified padding scheme.
Parameters
private_key: The RSA private keyciphertext: The encrypted datapadding: The encryption padding scheme (must match encryption)
Returns
Ok(plaintext) on success, Error(Nil) on decryption failure.
pub fn encrypt(
public_key: PublicKey,
plaintext: BitArray,
padding: EncryptPadding,
) -> Result(BitArray, Nil)
Encrypts data using RSA with the specified padding scheme.
Note: RSA encryption should only be used for small amounts of data (typically symmetric keys). For bulk encryption, use a symmetric cipher with a randomly generated key, then encrypt that key with RSA.
Parameters
public_key: The RSA public keyplaintext: The data to encryptpadding: The encryption padding scheme (EncryptPkcs1v15 or Oaep)
Returns
Ok(ciphertext) on success, Error(Nil) if plaintext is too long.
pub fn exponent1(key: PrivateKey) -> BitArray
Returns the first CRT exponent (dp = d mod (p-1)) as big-endian bytes.
This is part of the CRT (Chinese Remainder Theorem) parameters used for efficient RSA operations.
Parameters
key: The private key
Returns
The first CRT exponent as raw bytes.
pub fn exponent2(key: PrivateKey) -> BitArray
Returns the second CRT exponent (dq = d mod (q-1)) as big-endian bytes.
This is part of the CRT (Chinese Remainder Theorem) parameters used for efficient RSA operations.
Parameters
key: The private key
Returns
The second CRT exponent as raw bytes.
pub fn from_components(
n: BitArray,
e: BitArray,
d: BitArray,
) -> Result(#(PrivateKey, PublicKey), Nil)
Constructs an RSA private key from its components.
Creates a private key from the minimal set of components (n, e, d). CRT parameters are computed automatically using Miller’s algorithm.
Note: This function is not constant-time. The CRT parameter derivation involves operations that may leak timing information. This is acceptable for key import since the caller already possesses the secret material, but avoid calling this in timing-sensitive contexts.
Parameters
n: The modulus as big-endian bytese: The public exponent as big-endian bytesd: The private exponent as big-endian bytes
Returns
Ok(#(private_key, public_key)) on success, Error(Nil) if components are invalid.
Example
import kryptos/rsa
let assert Ok(#(private_key, _public_key)) = rsa.generate_key_pair(2048)
let n = rsa.modulus(private_key)
let e = rsa.public_exponent_bytes(private_key)
let d = rsa.private_exponent_bytes(private_key)
let assert Ok(#(reconstructed, _pub)) = rsa.from_components(n, e, d)
pub fn from_der(
der: BitArray,
format: PrivateKeyFormat,
) -> Result(#(PrivateKey, PublicKey), Nil)
Imports an RSA private key from DER-encoded data.
Parameters
der: DER-encoded key dataformat: The key format (Pkcs8 or Pkcs1)
Returns
Ok(#(private_key, public_key)) on success, Error(Nil) on failure.
pub fn from_full_components(
n: BitArray,
e: BitArray,
d: BitArray,
p: BitArray,
q: BitArray,
dp: BitArray,
dq: BitArray,
qi: BitArray,
) -> Result(#(PrivateKey, PublicKey), Nil)
Constructs an RSA private key from all components including CRT parameters.
This function works on both Erlang and JavaScript targets.
Parameters
n: The modulus as big-endian bytese: The public exponent as big-endian bytesd: The private exponent as big-endian bytesp: The first prime factor as big-endian bytesq: The second prime factor as big-endian bytesdp: The first CRT exponent (d mod (p-1)) as big-endian bytesdq: The second CRT exponent (d mod (q-1)) as big-endian bytesqi: The CRT coefficient (q^-1 mod p) as big-endian bytes
Returns
Ok(#(private_key, public_key)) on success, Error(Nil) if components are invalid.
pub fn from_pem(
pem: String,
format: PrivateKeyFormat,
) -> Result(#(PrivateKey, PublicKey), Nil)
Imports an RSA private key from PEM-encoded data.
Parameters
pem: PEM-encoded key stringformat: The key format (Pkcs8 or Pkcs1)
Returns
Ok(#(private_key, public_key)) on success, Error(Nil) on failure.
pub fn generate_key_pair(
bits: Int,
) -> Result(#(PrivateKey, PublicKey), Nil)
Generates an RSA key pair with the specified key size.
The key can be used for both signing and encryption operations.
Parameters
bits: The key size in bits (must be >= 1024)
Returns
Ok(#(private_key, public_key)) on success, Error(Nil) if bits < 1024.
Example
let assert Ok(#(private_key, public_key)) = rsa.generate_key_pair(2048)
pub fn modulus(key: PrivateKey) -> BitArray
Returns the modulus (n) as big-endian bytes for an RSA private key.
Parameters
key: The private key
Returns
The modulus as raw bytes.
pub fn modulus_bits(key: PrivateKey) -> Int
Returns the modulus size in bits for an RSA private key.
Parameters
key: The private key
Returns
The size of the modulus in bits (e.g., 2048, 4096).
pub fn prime1(key: PrivateKey) -> BitArray
Returns the first prime factor (p) as big-endian bytes.
The RSA modulus n = p * q. This is part of the CRT (Chinese Remainder Theorem) parameters used for efficient RSA operations.
Parameters
key: The private key
Returns
The first prime factor as raw bytes.
pub fn prime2(key: PrivateKey) -> BitArray
Returns the second prime factor (q) as big-endian bytes.
The RSA modulus n = p * q. This is part of the CRT (Chinese Remainder Theorem) parameters used for efficient RSA operations.
Parameters
key: The private key
Returns
The second prime factor as raw bytes.
pub fn private_exponent_bytes(key: PrivateKey) -> BitArray
Returns the private exponent (d) as big-endian bytes for an RSA private key.
Parameters
key: The private key
Returns
The private exponent as raw bytes.
pub fn public_exponent(key: PrivateKey) -> Int
Returns the public exponent for an RSA private key.
Parameters
key: The private key
Returns
The public exponent (commonly 65537).
pub fn public_exponent_bytes(key: PrivateKey) -> BitArray
Returns the public exponent (e) as big-endian bytes for an RSA private key.
Parameters
key: The private key
Returns
The public exponent as raw bytes.
pub fn public_key_exponent(key: PublicKey) -> Int
Returns the public exponent for an RSA public key.
Parameters
key: The public key
Returns
The public exponent (commonly 65537).
pub fn public_key_exponent_bytes(key: PublicKey) -> BitArray
Returns the public exponent (e) as big-endian bytes for an RSA public key.
Parameters
key: The public key
Returns
The public exponent as raw bytes.
pub fn public_key_from_components(
n: BitArray,
e: BitArray,
) -> Result(PublicKey, Nil)
Constructs an RSA public key from its components.
Parameters
n: The modulus as big-endian bytese: The public exponent as big-endian bytes
Returns
Ok(public_key) on success, Error(Nil) if components are invalid.
pub fn public_key_from_der(
der: BitArray,
format: PublicKeyFormat,
) -> Result(PublicKey, Nil)
Imports an RSA public key from DER-encoded data.
Parameters
der: DER-encoded key dataformat: The key format (Spki or RsaPublicKey)
Returns
Ok(public_key) on success, Error(Nil) on failure.
pub fn public_key_from_pem(
pem: String,
format: PublicKeyFormat,
) -> Result(PublicKey, Nil)
Imports an RSA public key from PEM-encoded data.
Parameters
pem: PEM-encoded key stringformat: The key format (Spki or RsaPublicKey)
Returns
Ok(public_key) on success, Error(Nil) on failure.
pub fn public_key_from_private_key(key: PrivateKey) -> PublicKey
Derives the public key from an RSA private key.
Parameters
key: The private key
Returns
The corresponding public key.
pub fn public_key_modulus(key: PublicKey) -> BitArray
Returns the modulus (n) as big-endian bytes for an RSA public key.
Parameters
key: The public key
Returns
The modulus as raw bytes.
pub fn public_key_modulus_bits(key: PublicKey) -> Int
Returns the modulus size in bits for an RSA public key.
Parameters
key: The public key
Returns
The size of the modulus in bits (e.g., 2048, 4096).
pub fn public_key_to_der(
key: PublicKey,
format: PublicKeyFormat,
) -> Result(BitArray, Nil)
Exports an RSA public key to DER format.
Parameters
key: The public key to exportformat: The output format (Spki or RsaPublicKey)
Returns
Ok(der_data) on success, Error(Nil) on failure.
pub fn public_key_to_pem(
key: PublicKey,
format: PublicKeyFormat,
) -> Result(String, Nil)
Exports an RSA public key to PEM format.
Parameters
key: The public key to exportformat: The output format (Spki or RsaPublicKey)
Returns
Ok(pem_string) on success, Error(Nil) on failure.
pub fn sign(
private_key: PrivateKey,
message: BitArray,
hash: hash.HashAlgorithm,
padding: SignPadding,
) -> BitArray
Signs a message using RSA with the specified hash algorithm and padding.
The message is hashed internally using the provided algorithm before signing.
Parameters
private_key: An RSA private keymessage: The message to sign (any length)hash: The hash algorithm to usepadding: The signature padding scheme (Pkcs1v15 or Pss)
Returns
The RSA signature.
pub fn to_der(
key: PrivateKey,
format: PrivateKeyFormat,
) -> Result(BitArray, Nil)
Exports an RSA private key to DER format.
Parameters
key: The private key to exportformat: The output format (Pkcs8 or Pkcs1)
Returns
Ok(der_data) on success, Error(Nil) on failure.
pub fn to_pem(
key: PrivateKey,
format: PrivateKeyFormat,
) -> Result(String, Nil)
Exports an RSA private key to PEM format.
Parameters
key: The private key to exportformat: The output format (Pkcs8 or Pkcs1)
Returns
Ok(pem_string) on success, Error(Nil) on failure.
pub fn verify(
public_key: PublicKey,
message message: BitArray,
signature signature: BitArray,
hash hash: hash.HashAlgorithm,
padding padding: SignPadding,
) -> Bool
Verifies an RSA signature against a message.
The message is hashed internally using the provided algorithm before verification. The same hash algorithm and padding used during signing must be used for verification.
Parameters
public_key: The RSA public key corresponding to the signing keymessage: The original message that was signedsignature: The signature to verifyhash: The hash algorithm used during signingpadding: The signature padding scheme used during signing
Returns
True if the signature is valid, False otherwise.