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 builder for constructing CSRs.

pub opaque type Builder

Phantom type marker for CSRs created via the builder.

pub type Built

A Certificate Signing Request.

The phantom type parameter tracks how the CSR was created:

  • Csr(Built) - created via sign_with_ecdsa or sign_with_rsa
  • Csr(Parsed) - created via from_pem or from_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)

Error type for CSR parsing failures.

pub type CsrError {
  InvalidPem
  InvalidStructure
  UnsupportedSignatureAlgorithm(x509.Oid)
  UnsupportedKeyType(x509.Oid)
  SignatureVerificationFailed
  UnsupportedVersion(Int)
}

Constructors

  • InvalidPem
  • InvalidStructure
  • UnsupportedSignatureAlgorithm(x509.Oid)
  • UnsupportedKeyType(x509.Oid)
  • SignatureVerificationFailed
  • UnsupportedVersion(Int)

Phantom type marker for CSRs parsed from PEM/DER.

pub type Parsed

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 builder
  • key: An EC private key from ec.generate_key_pair
  • hash: The hash algorithm for signing. Recommended: Sha256 for P-256, Sha384 for P-384, Sha512 for P-521. Note: Sha1 is supported for legacy compatibility but is cryptographically weak and should be avoided.

Returns

  • Ok(Csr(Built)) containing the signed CSR
  • Error(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 builder
  • key: An EdDSA private key from eddsa.generate_key_pair

Returns

  • Ok(Csr(Built)) containing the signed CSR
  • Error(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 builder
  • key: An RSA private key from rsa.generate_key_pair
  • hash: The hash algorithm for signing. Recommended: Sha256 for 2048-bit keys, Sha384 or Sha512 for 3072-bit or larger keys. Note: Sha1 is supported for legacy compatibility but is cryptographically weak and should be avoided.

Returns

  • Ok(Csr(Built)) containing the signed CSR
  • Error(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 builder
  • name: A DNS hostname (e.g., “example.com” or “*.example.com”)

Returns

  • Ok(Builder) with the updated builder
  • Error(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 builder
  • email: An email address (e.g., “user@example.com”)

Returns

  • Ok(Builder) with the updated builder
  • Error(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 builder
  • ip: An IPv4 address (e.g., “192.168.1.1”) or IPv6 address (e.g., “2001:db8::1”, “::1”)

Returns

  • Ok(Builder) with the updated builder
  • Error(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 builder
  • subject: A distinguished name created with x509.name

Returns

The updated builder.

Search Document