Building a KeyGenerator Demo Project from Scratch

KeyGenerator Demo Project — Quick Start GuideThis guide walks you through the KeyGenerator demo project from setup to basic usage, explaining core concepts, example code, common configurations, and best practices for testing and deployment. It’s written for developers with basic programming knowledge who want a practical, hands-on introduction to implementing a simple cryptographic key-generation component and integrating it into a small demo application.


What this project is and why it matters

A KeyGenerator demo project provides a compact, practical example of generating cryptographic keys (symmetric or asymmetric), managing them securely in memory or simple storage, and using them for common tasks like encryption, signing, and verification. This demo is useful for:

  • Rapidly learning key-generation APIs in a chosen language/platform.
  • Prototyping how keys integrate into authentication, encryption, or secure storage flows.
  • Demonstrating secure defaults and common pitfalls in key handling.

Key goals of this guide:

  • Show how to set up the demo project.
  • Explain the core key generation concepts used.
  • Provide runnable example code for generating keys and performing encryption/signing.
  • Cover basic testing and deployment considerations.

Prerequisites

  • Basic programming experience (language-specific sections list required versions).
  • Familiarity with the command line and package managers (npm, pip, cargo, etc.) for your chosen language.
  • Optional: basic understanding of cryptography concepts (symmetric vs. asymmetric keys, public/private pairs, key sizes).

Choosing symmetric vs. asymmetric keys — quick comparison

Aspect Symmetric (e.g., AES) Asymmetric (e.g., RSA, ECC)
Use cases Encrypting data at rest or in transit between trusted parties Key exchange, digital signatures, public-key encryption
Key size (typical) 128–256 bits 2048+ bits (RSA) or 256 bits (ECC)
Performance Fast Slower, more CPU-intensive
Key distribution Requires secure channel Public key simplifies distribution

Project structure (example)

A simple demo project might use this layout:

  • README.md — overview and how to run
  • /src — source code
    • main program or server
    • keygen module
    • crypto utils (encrypt/decrypt, sign/verify)
  • /tests — unit/integration tests
  • /examples — small usage examples or scripts
  • config (optional) — key parameters, storage paths

Example: Node.js demo (AES and RSA)

Below are concise, ready-to-run examples for a Node.js KeyGenerator demo. Use Node.js 18+.

  1. Initialize:

    mkdir keygenerator-demo cd keygenerator-demo npm init -y npm install node-forge 
  2. src/keygen.js — generate AES and RSA keys: “`javascript import forge from ‘node-forge’; import fs from ‘fs’;

export function generateAesKey(bits = 256) { // Returns raw bytes encoded in hex const key = forge.random.getBytesSync(bits / 8); return forge.util.bytesToHex(key); }

export function generateRsaKeyPair(bits = 2048) { const keypair = forge.pki.rsa.generateKeyPair({ bits: bits, e: 0x10001 }); const publicPem = forge.pki.publicKeyToPem(keypair.publicKey); const privatePem = forge.pki.privateKeyToPem(keypair.privateKey); return { publicPem, privatePem }; }

export function saveKey(path, content) { fs.writeFileSync(path, content, { mode: 0o600 }); }


3) src/crypto.js — encrypt/decrypt with AES-GCM and sign/verify with RSA: ```javascript import forge from 'node-forge'; export function aesGcmEncrypt(hexKey, plaintext) {   const key = forge.util.hexToBytes(hexKey);   const iv = forge.random.getBytesSync(12);   const cipher = forge.cipher.createCipher('AES-GCM', key);   cipher.start({ iv: iv, tagLength: 128 });   cipher.update(forge.util.createBuffer(plaintext, 'utf8'));   cipher.finish();   const ciphertext = cipher.output.getBytes();   const tag = cipher.mode.tag.getBytes();   return {     iv: forge.util.bytesToHex(iv),     ciphertext: forge.util.bytesToHex(ciphertext),     tag: forge.util.bytesToHex(tag)   }; } export function aesGcmDecrypt(hexKey, ivHex, ciphertextHex, tagHex) {   const key = forge.util.hexToBytes(hexKey);   const iv = forge.util.hexToBytes(ivHex);   const ciphertext = forge.util.hexToBytes(ciphertextHex);   const tag = forge.util.hexToBytes(tagHex);   const decipher = forge.cipher.createDecipher('AES-GCM', key);   decipher.start({ iv: iv, tagLength: 128, tag: tag });   decipher.update(forge.util.createBuffer(ciphertext));   const success = decipher.finish();   if (!success) throw new Error('Decryption failed or authentication tag mismatch');   return decipher.output.toString('utf8'); } export function rsaSign(privatePem, message) {   const privateKey = forge.pki.privateKeyFromPem(privatePem);   const md = forge.md.sha256.create();   md.update(message, 'utf8');   const signature = privateKey.sign(md);   return forge.util.bytesToHex(signature); } export function rsaVerify(publicPem, message, signatureHex) {   const publicKey = forge.pki.publicKeyFromPem(publicPem);   const md = forge.md.sha256.create();   md.update(message, 'utf8');   const signature = forge.util.hexToBytes(signatureHex);   return publicKey.verify(md.digest().bytes(), signature); } 
  1. src/index.js — demo runner: “`javascript import { generateAesKey, generateRsaKeyPair, saveKey } from ‘./keygen.js’; import { aesGcmEncrypt, aesGcmDecrypt, rsaSign, rsaVerify } from ‘./crypto.js’;

const aesKeyHex = generateAesKey(256); console.log(‘AES key (hex):’, aesKeyHex);

const { publicPem, privatePem } = generateRsaKeyPair(2048); console.log(‘RSA public key PEM: ‘, publicPem); saveKey(’./private.pem’, privatePem); saveKey(‘./public.pem’, publicPem);

const text = ‘Hello KeyGenerator demo’; const enc = aesGcmEncrypt(aesKeyHex, text); console.log(‘Encrypted:’, enc);

const dec = aesGcmDecrypt(aesKeyHex, enc.iv, enc.ciphertext, enc.tag); console.log(‘Decrypted:’, dec);

const sig = rsaSign(privatePem, text); console.log(‘Signature (hex):’, sig); console.log(‘Signature valid:’, rsaVerify(publicPem, text, sig));


Run: ```bash node --experimental-modules src/index.js 

Example: Python demo (cryptography library)

Install:

python -m venv venv source venv/bin/activate pip install cryptography 

src/keygen.py:

from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.hkdf import HKDF from cryptography.hazmat.primitives.ciphers.aead import AESGCM import os def generate_aes_key(bits=256):     return AESGCM.generate_key(bit_length=bits) def generate_rsa_keypair(bits=2048):     private_key = rsa.generate_private_key(public_exponent=65537, key_size=bits)     public_key = private_key.public_key()     priv_pem = private_key.private_bytes(         encoding=serialization.Encoding.PEM,         format=serialization.PrivateFormat.TraditionalOpenSSL,         encryption_algorithm=serialization.NoEncryption()     )     pub_pem = public_key.public_bytes(         encoding=serialization.Encoding.PEM,         format=serialization.PublicFormat.SubjectPublicKeyInfo     )     return pub_pem, priv_pem def aes_gcm_encrypt(key, plaintext):     aesgcm = AESGCM(key)     iv = os.urandom(12)     ct = aesgcm.encrypt(iv, plaintext.encode('utf-8'), None)     return iv.hex(), ct.hex() def aes_gcm_decrypt(key, iv_hex, ct_hex):     aesgcm = AESGCM(key)     iv = bytes.fromhex(iv_hex)     ct = bytes.fromhex(ct_hex)     pt = aesgcm.decrypt(iv, ct, None)     return pt.decode('utf-8') 

Secure defaults and recommendations

  • Use authenticated encryption (e.g., AES-GCM or ChaCha20-Poly1305).
  • Prefer 256-bit symmetric keys and 2048+ bit RSA or P-256/P-384 ECC for asymmetric keys.
  • Protect private keys on disk with strict file permissions and, when possible, encryption at rest or hardware security modules (HSMs).
  • Don’t hard-code keys in source code or repos. Use environment variables or secret managers for configuration.
  • Rotate keys periodically and provide a clear key-rotation plan in production systems.
  • Validate cryptographic library versions and keep dependencies up to date.

Testing the demo

  • Unit tests for key generation functions: assert key lengths and formats.
  • Encrypt/decrypt roundtrip tests: ensure plaintext matches decrypted output.
  • Signature tests: sign then verify; verify should fail with modified message.
  • Fuzz tests: feed random inputs into parsers to catch edge cases.

Deployment notes

  • For demos, storing keys in files with 0600 permissions is acceptable; for production, use a secret manager (AWS KMS/Secrets Manager, GCP KMS/Secret Manager, HashiCorp Vault) or an HSM.
  • If running as a service, limit access to key files by service account and container.
  • Consider using ephemeral keys for short-lived sessions (derive via HKDF from a master secret).
  • Log only non-sensitive metadata — never log keys, raw ciphertext with metadata that can be used to decrypt, or private PEMs.

Common pitfalls

  • Reusing IVs/nonces with the same key (catastrophic for AES-GCM/ChaCha20-Poly1305).
  • Insufficient key sizes or weak RNG sources.
  • Improper PEM parsing or accepting untrusted key material without validation.
  • Storing keys in version control.

Next steps and extensions

  • Add support for hardware-backed keys (PKCS#11, Windows CNG, macOS Secure Enclave).
  • Integrate with a secrets manager or KMS.
  • Extend examples to TLS client/server using generated certificates (self-signed for demo).
  • Implement key rotation workflows and key metadata tracking.

If you want, I can:

  • Provide a complete ready-to-run repository for Node.js or Python.
  • Add Dockerfile and CI test examples.
  • Expand the article with diagrams or a step-by-step key-rotation implementation.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *