kryptos/x509/csr
X.509 Certificate Signing Request (CSR) generation.
This module provides a builder for creating PKCS#10 Certificate Signing Requests. CSRs are used to request certificates from a Certificate Authority.
Example
import gleam/result
import kryptos/ec
import kryptos/hash
import kryptos/x509
import kryptos/x509/csr
let #(private_key, _) = ec.generate_key_pair(ec.P256)
let subject = x509.name([
x509.cn("example.com"),
x509.organization("Acme Inc"),
x509.country("US"),
])
let assert Ok(builder) =
csr.new()
|> csr.with_subject(subject)
|> csr.with_dns_name("example.com")
|> result.try(csr.with_dns_name(_, "www.example.com"))
let assert Ok(my_csr) = csr.sign_with_ecdsa(builder, private_key, hash.Sha256)
let pem = csr.to_pem(my_csr)
Types
A Certificate Signing Request.
The phantom type parameter tracks how the CSR was created:
Csr(Built)- created viasign_with_ecdsaorsign_with_rsaCsr(Parsed)- created viafrom_pemorfrom_der
Export functions (to_pem, to_der) work on any Csr(a).
Accessor functions (subject, public_key, etc.) require Csr(Parsed).
pub opaque type Csr(status)
Values
pub fn attributes(
csr: Csr(Parsed),
) -> List(#(x509.Oid, BitArray))
Returns any non-extension attributes as raw (OID, value) pairs.
Most CSRs only have the extensionRequest attribute, so this is typically empty.
pub fn extensions(
csr: Csr(Parsed),
) -> List(#(x509.Oid, Bool, BitArray))
Returns any extensions beyond SANs as raw (OID, critical, value) tuples.
This allows access to extensions that kryptos doesn’t have typed representations for. The Bool indicates whether the extension was marked as critical per RFC 5280.
pub fn from_der(der: BitArray) -> Result(Csr(Parsed), CsrError)
Parse a DER-encoded CSR and verify its signature.
pub fn from_der_unverified(
der: BitArray,
) -> Result(Csr(Parsed), CsrError)
Parse a DER-encoded CSR without verifying the signature.
Useful for debugging malformed or partially valid CSRs. The parsed fields may not be trustworthy since the signature was not verified.
pub fn from_pem(pem: String) -> Result(Csr(Parsed), CsrError)
Parse a PEM-encoded CSR and verify its signature.
Returns an error if the PEM is invalid, the structure is malformed, or the signature doesn’t verify against the embedded public key.
pub fn from_pem_unverified(
pem: String,
) -> Result(Csr(Parsed), CsrError)
Parse a PEM-encoded CSR without verifying the signature.
Useful for debugging malformed or partially valid CSRs. The parsed fields may not be trustworthy.
pub fn new() -> Builder
Creates a new CSR builder with an empty subject and no extensions.
Use the with_* functions to configure the builder, then call
sign_with_ecdsa or sign_with_rsa to generate the signed CSR.
Returns
A new Builder ready for configuration.
pub fn public_key(csr: Csr(Parsed)) -> x509.PublicKey
Returns the public key embedded in a parsed CSR.
This is the key that the requester wants certified.
Parameters
csr: A parsed CSR
Returns
The subject’s public key (RSA, EC, or EdDSA).
pub fn sign_with_ecdsa(
builder: Builder,
key: ec.PrivateKey,
hash: hash.HashAlgorithm,
) -> Result(Csr(Built), Nil)
Signs the CSR with an ECDSA private key.
The public key is derived from the private key and included in the CSR. The resulting CSR can be submitted to a Certificate Authority.
Parameters
builder: The configured CSR builderkey: An EC private key fromec.generate_key_pairhash: The hash algorithm for signing. Recommended:Sha256for P-256,Sha384for P-384,Sha512for P-521. Note:Sha1is supported for legacy compatibility but is cryptographically weak and should be avoided.
Returns
Ok(Csr(Built))containing the signed CSRError(Nil)if the hash algorithm is not supported or the public key cannot be encoded
pub fn sign_with_eddsa(
builder: Builder,
key: eddsa.PrivateKey,
) -> Result(Csr(Built), Nil)
Signs the CSR with an EdDSA private key (Ed25519 or Ed448).
Note: Support for EdDSA is limited with browsers and certificate authorities.
Parameters
builder: The configured CSR builderkey: An EdDSA private key fromeddsa.generate_key_pair
Returns
Ok(Csr(Built))containing the signed CSRError(Nil)if the public key cannot be encoded
pub fn sign_with_rsa(
builder: Builder,
key: rsa.PrivateKey,
hash: hash.HashAlgorithm,
) -> Result(Csr(Built), Nil)
Signs the CSR with an RSA private key using PKCS#1 v1.5 padding.
The public key is derived from the private key and included in the CSR. The resulting CSR can be submitted to a Certificate Authority.
Parameters
builder: The configured CSR builderkey: An RSA private key fromrsa.generate_key_pairhash: The hash algorithm for signing. Recommended:Sha256for 2048-bit keys,Sha384orSha512for 3072-bit or larger keys. Note:Sha1is supported for legacy compatibility but is cryptographically weak and should be avoided.
Returns
Ok(Csr(Built))containing the signed CSRError(Nil)if the hash algorithm is not supported or the public key cannot be encoded
pub fn signature_algorithm(
csr: Csr(Parsed),
) -> x509.SignatureAlgorithm
Returns the signature algorithm used to sign the CSR.
Parameters
csr: A parsed CSR
Returns
The signature algorithm identifier.
pub fn subject(csr: Csr(Parsed)) -> x509.Name
Returns the subject (distinguished name) of a parsed CSR.
The subject identifies who the certificate is being requested for.
Parameters
csr: A parsed CSR
Returns
The subject as a distinguished name.
pub fn subject_alt_names(
csr: Csr(Parsed),
) -> List(x509.SubjectAltName)
Returns the Subject Alternative Names from the CSR.
Parameters
csr: A parsed CSR
Returns
List of SANs (DNS names, emails, IPs), or empty list if no SAN extension was requested.
pub fn to_der(csr: Csr(a)) -> BitArray
Exports the CSR as DER-encoded bytes.
DER (Distinguished Encoding Rules) is a binary format commonly used for programmatic certificate handling.
Parameters
csr: The signed CSR (either built or parsed)
Returns
The raw DER-encoded CSR bytes.
pub fn to_pem(csr: Csr(a)) -> String
Exports the CSR as a PEM-encoded string.
PEM (Privacy-Enhanced Mail) is a Base64-encoded format with header and footer lines. This is the format typically required when submitting a CSR to a Certificate Authority.
Parameters
csr: The signed CSR (either built or parsed)
Returns
A PEM-encoded string with -----BEGIN CERTIFICATE REQUEST----- headers.
pub fn version(csr: Csr(Parsed)) -> Int
Returns the version of a parsed CSR.
PKCS#10 v1 CSRs always have version 0.
Parameters
csr: A parsed CSR
Returns
The version number (always 0 for PKCS#10 v1).
pub fn with_dns_name(
builder: Builder,
name: String,
) -> Result(Builder, Nil)
Adds a DNS name to the Subject Alternative Names extension.
SANs allow a certificate to be valid for multiple hostnames. Modern browsers require the domain to appear in the SAN extension, not just the Common Name.
Parameters
builder: The CSR buildername: A DNS hostname (e.g., “example.com” or “*.example.com”)
Returns
Ok(Builder)with the updated builderError(Nil)if the DNS name contains non-ASCII characters
pub fn with_email(
builder: Builder,
email: String,
) -> Result(Builder, Nil)
Adds an email address to the Subject Alternative Names extension.
Used for S/MIME certificates where the certificate should be valid for a specific email address.
Parameters
builder: The CSR builderemail: An email address (e.g., “user@example.com”)
Returns
Ok(Builder)with the updated builderError(Nil)if the email contains non-ASCII characters
pub fn with_ip(
builder: Builder,
ip: String,
) -> Result(Builder, Nil)
Adds an IP address to the Subject Alternative Names extension.
Allows the certificate to be valid when accessed by IP address instead of hostname.
Parameters
builder: The CSR builderip: An IPv4 address (e.g., “192.168.1.1”) or IPv6 address (e.g., “2001:db8::1”, “::1”)
Returns
Ok(Builder)with the updated builderError(Nil)if the IP address cannot be parsed
pub fn with_subject(
builder: Builder,
subject: x509.Name,
) -> Builder
Sets the distinguished name subject for the CSR.
The subject identifies who the certificate will be issued to.
Parameters
builder: The CSR buildersubject: A distinguished name created withx509.name
Returns
The updated builder.