Daraja.SecurityCredential (daraja v0.1.0)

Copy Markdown View Source

Utilities for building Daraja security credentials.

Safaricom expects the initiator password encrypted with the portal-provided certificate/public key and Base64 encoded. Used by B2B and B2C PaymentRequest modules; also callable directly.

Download the encryption certificate from the Daraja developer portal only.

Pinning trusted certificates

When :security_credential_pins is set, PEM inputs must match a configured SPKI SHA-256 fingerprint before encryption:

config :daraja,
  environment: :production,
  security_credential_pins: ["yGsAE85gJh3satQK/3DRqZCjovsVGOqmUQ22wXvoIko"]

Generate a pin from a portal certificate with spki_fingerprint/1.

Pinning is skipped when the list is empty. In :sandbox, set :enforce_security_credential_pins to false to disable pinning during local development. Production always enforces when pins are configured.

Tuple credentials ({password, pem})

Tuple inputs are encrypted on first use and cached in :persistent_term. For production, pre-encrypt at deploy time and pass only the Base64 string.

Disable tuple credentials in production:

config :daraja,
  environment: :production,
  allow_tuple_security_credential: false

A one-time warning is logged when tuples are used (disable with :warn_tuple_security_credential: false).

Summary

Functions

Encrypts a plaintext initiator password using the provided PEM certificate or PEM public key and returns a Base64 encoded security credential.

Resolves a security_credential input to an encrypted Base64 string.

Returns the SHA-256 SPKI fingerprint (Base64) for a PEM certificate or public key.

Types

encrypt_error()

@type encrypt_error() ::
  :invalid_public_key
  | :encryption_failed
  | :untrusted_public_key
  | :tuple_credentials_disabled

Functions

encrypt(password, pem)

@spec encrypt(String.t(), String.t()) :: {:ok, String.t()} | {:error, encrypt_error()}

Encrypts a plaintext initiator password using the provided PEM certificate or PEM public key and returns a Base64 encoded security credential.

resolve(credential)

@spec resolve(String.t() | {String.t(), String.t()} | nil | term()) ::
  {:ok, String.t() | nil} | {:error, encrypt_error() | :invalid_format}

Resolves a security_credential input to an encrypted Base64 string.

Accepts:

  • A pre-encrypted Base64 string — returned as-is.
  • A {password, pem} tuple — encrypts using encrypt/2.
  • nil — returned as {:ok, nil} so the missing-field check in PaymentRequest.new/1 can report it normally.
  • Any other value — returns {:error, :invalid_format}.

spki_fingerprint(pem)

@spec spki_fingerprint(String.t()) ::
  {:ok, String.t()} | {:error, :invalid_public_key}

Returns the SHA-256 SPKI fingerprint (Base64) for a PEM certificate or public key.

Use the value in :security_credential_pins.