Daraja SDK Logomark
Daraja SDK
Guides

Generating a Security Credential

The one-time, offline step this SDK deliberately doesn't automate.

B2C Account Top Up needs a securityCredential your Initiator password, RSA-encrypted with Safaricom's public certificate, then Base64-encoded. This page walks through generating it once. This SDK does not do this step for you, on purpose.

Why this isn't automated in the SDK

Encrypting the Initiator password requires embedding Safaricom's public certificate as a dependency a certificate that gets rotated on Safaricom's own schedule, independent of this package's release cycle. Baking it into @lumierelabs/daraja would mean either shipping a certificate that silently goes stale, or adding an update mechanism that fetches and trusts a certificate at runtime, which is a meaningfully different (and riskier) security posture than a one-time offline step you control yourself.

Steps

Get your Initiator credentials

Your Initiator username and password are issued by Safaricom as part of your Go-Live application for B2C/B2B products not the same as your Consumer Key/Secret. In sandbox, use the shared test initiator (testapi) and its published test password from the Daraja portal's Test Credentials page.

Get Safaricom's public certificate

Sandbox and production use different certificates. Both are linked from the Daraja documentation's Test Credentials / Go-Live sections download the correct one for your target environment. Using the sandbox certificate against production (or vice versa) produces a SecurityCredential that looks structurally valid but is silently rejected by Daraja.

Encrypt the password

RSA-encrypt your Initiator password using the certificate (PKCS1 padding), then Base64-encode the result. Safaricom's Daraja documentation links an online tool for this; if you'd rather not paste a production password into a browser tool, do it locally instead:

openssl rsautl -encrypt -certin -inkey cert.cer -in password.txt | base64

Where password.txt contains your raw Initiator password (no trailing newline) and cert.cer is the certificate from the previous step.

Store the result as a secret

The output is a single Base64 string this is your securityCredential. Store it as an environment variable or secret, exactly the way you'd store DARAJA_CONSUMER_SECRET. Pass it straight through to the SDK:

await daraja.b2cTopUp.topUp({
  initiator: "testapi",
  securityCredential: process.env.DARAJA_SECURITY_CREDENTIAL!,
  // ...
});

This does not need to happen per-request

securityCredential is stable until you rotate your Initiator password generate it once and reuse it across every B2C Top Up call. Re-encrypting it on every request (or worse, doing it inside a hot request path) adds nothing but latency and a needless dependency on an encryption library at runtime.

On this page