Skip to content

itssadon/firs-irn-qr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

firs-irn-qr

A simple Node.js + TypeScript library and CLI for encrypting IRNs and generating QR codes based on the FIRS (Nigeria) e-Invoicing IRN Signing Guide.

This package implements the IRN signing and QR generation process described in the FIRS e-Invoicing documentation, providing a developer-friendly API for automation and integration.


✨ Features

  • 🔐 Encrypt IRN + certificate using FIRS public key (RSA PKCS#1 v1.5)
  • 🕒 Automatically appends UNIX timestamp to IRN (e.g. INV001-123ABC.1731618237)
  • 📦 Outputs expected artifacts:
    • public_key.pem
    • data.json
    • encrypted_data.bin
    • encrypted_data.txt
    • qr_code.png
  • 🧾 Generate QR codes from encrypted Base64 data
  • ⚙️ Works both as a CLI tool and as a Node.js library

📦 Installation

npm install firs-irn-qr

or

yarn add firs-irn-qr
# or
pnpm add firs-irn-qr

🚀 Usage

🖥️ CLI

The CLI lets you easily encrypt an IRN and generate a QR code.

Basic Example

export FIRS_PUBLIC_KEY="<Base64-of-PEM or full PEM string>"
export FIRS_CERTIFICATE="<Base64 certificate>"

npx firs-irn-qr sign   --public-key "$FIRS_PUBLIC_KEY"   --certificate "$FIRS_CERTIFICATE"   --irn INV001-345SFG-20241011   --outdir ./out

🗂 Output files in ./out/:

public_key.pem
data.json
encrypted_data.bin
encrypted_data.txt
qr_code.png

With a custom timestamp

npx firs-irn-qr sign   -p "$FIRS_PUBLIC_KEY"   -c "$FIRS_CERTIFICATE"   -i INV001-345SFG-20241011   -t 1731618237

Skip QR generation

npx firs-irn-qr sign   -p "$FIRS_PUBLIC_KEY"   -c "$FIRS_CERTIFICATE"   -i INV001-345SFG-20241011   --no-qr

Using a full IRN string that already includes the timestamp

npx firs-irn-qr sign   -p "$FIRS_PUBLIC_KEY"   -c "$FIRS_CERTIFICATE"   -i "INV001-345SFG-20241011.1731618237"

💻 Library API

Use the module in your Node.js/TypeScript project:

import { signAndEncode, writeQrPng } from 'firs-irn-qr';

const keys = {
  public_key: process.env.FIRS_PUBLIC_KEY!,    // Base64 or PEM string
  certificate: process.env.FIRS_CERTIFICATE!,  // Base64 string
};

const { encryptedBase64, irnWithTimestamp, publicKeyPem, dataJson } =
  await signAndEncode({
    keys,
    irn: 'INV001-345SFG-20241011',
  });

console.log('IRN:', irnWithTimestamp);
console.log('Encrypted data (Base64):', encryptedBase64);

// Optional: generate QR code
await writeQrPng(encryptedBase64, './qr_code.png');

🧩 API Reference

signAndEncode({ keys, irn, timestamp? })

Param Type Description
keys.public_key string FIRS public key (Base64 or PEM)
keys.certificate string Certificate (Base64 string)
irn string IRN stem (e.g. INV001-345SFG-20241011)
timestamp? number UNIX timestamp in seconds

Returns:

{
  publicKeyPem: string;
  irnWithTimestamp: string;
  dataJson: string;
  encrypted: Buffer;
  encryptedBase64: string;
}

writeQrPng(base64CipherText, outFile)

Generates a QR code PNG from the Base64 encrypted string.

signAndQrDataUrl({ keys, irn, timestamp? })

Param Type Description
keys.public_key string FIRS public key (Base64 or PEM)
keys.certificate string Certificate (Base64 string)
irn string IRN stem (e.g. INV001-345SFG-20241011)
timestamp? number UNIX timestamp in seconds

Returns:

{
  publicKeyPem: string;
  irnWithTimestamp: string;
  dataJson: string;
  encrypted: Buffer;
  encryptedBase64: string;
  qrDataUrl: string;
}

🔒 How it maps to the FIRS shell guide

FIRS Step Equivalent in this Package
`jq -r '.public_key' ... openssl base64 -d -out public_key.pem`
jq --arg irn ... '{ irn: $irn, certificate: .certificate }' makeDataJson() constructs the JSON
openssl pkeyutl -encrypt ... Node crypto.publicEncrypt using RSA PKCS#1 v1.5
base64 -i encrypted_data.bin -o encrypted_data.txt Built-in Base64 conversion
qrencode -o qr_code.png -t PNG < encrypted_data.txt writeQrPng() via the qrcode package

⚠️ Notes & Assumptions

  • Uses RSA PKCS#1 v1.5 padding (same as openssl pkeyutl -encrypt)

  • Compatible with standard 2048-bit RSA public keys

  • Payload format:

    {
      "irn": "INV001-ABC123.1731618237",
      "certificate": "Base64string..."
    }
  • Timestamps use UNIX seconds (not milliseconds)

  • Only public key encryption — no private key or decryption logic included


🧾 Example output

After successful execution, your output directory contains:

public_key.pem
data.json
encrypted_data.bin
encrypted_data.txt
qr_code.png

Scan qr_code.png with your MBS360 app or FIRS verifier to validate.


🧠 Troubleshooting

Error Cause Fix
bad base64 Invalid key or malformed string Ensure your public key is valid Base64 or PEM
data too large for key size Payload exceeds RSA key capacity Use shorter IRN/certificate or a larger key
QR unreadable Used binary instead of Base64 Ensure you pass Base64 data to writeQrPng()

📜 License

MIT © 2025 @itssadon


🌐 Links

About

FIRS Invoice Reference Number (IRN) QR NPM Package

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages