Back to skills
SKILL.md
Stanford Crypto Patterns
ASecuritySide-channel-resistant cryptography patterns from Stanford SJCL. Constant-time operations, AES-CCM authenticated encryption, PBKDF2 key derivation, random number generation, and timing-attack-safe comparisons. Sources: bitwiseshiftleft/sjcl (Stanford JavaScript Crypto Library).
- 10 stars
- 0 votes
- 0 copies
- 1 view
- Added September 9, 2026
Works with
Security analysis
100/100npx -y skills add yanacuti1121/Yana-AI --skill stanford-crypto-patterns --agent claude-codeAre you the author of Stanford Crypto Patterns?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/yanacuti1121-stanford-crypto-patterns)---
name: stanford-crypto-patterns
description: Side-channel-resistant cryptography patterns from Stanford SJCL. Constant-time operations, AES-CCM authenticated encryption, PBKDF2 key derivation, random number generation, and timing-attack-safe comparisons. Sources: bitwiseshiftleft/sjcl (Stanford JavaScript Crypto Library).
origin: yana-ai — synthesized from bitwiseshiftleft/sjcl (BSD-2-Clause, Stanford University)
license: Apache-2.0
version: 1.0.0
compatibility: yana-ai >= 1.3.49
---
# /stanford-crypto-patterns
## When to Use
- Environments where timing-attack resistance is critical (secret comparison)
- AES-CCM authenticated encryption (alternative to GCM with simpler nonce handling)
- SJCL PRNG for cryptographic random number generation
- Academic/compliance contexts requiring vetted, peer-reviewed crypto library
## Do NOT use for
- New Node.js code — prefer built-in `crypto` module (WebCrypto API) for standard cases
- Performance-critical bulk encryption (pure JS SJCL is slower than native C bindings)
---
## Constant-time comparison (timing-attack safe)
```javascript
import sjcl from 'sjcl'
// WRONG: regular string comparison leaks timing info
// if (secretA === secretB) ... ← fails early on first mismatch
// RIGHT: constant-time comparison via XOR of bitArrays
function constantTimeEqual(a: string, b: string): boolean {
if (a.length !== b.length) return false
const aWords = sjcl.codec.utf8String.toBits(a)
const bWords = sjcl.codec.utf8String.toBits(b)
let diff = 0
for (let i = 0; i < aWords.length; i++) {
diff |= aWords[i] ^ bWords[i]
}
return diff === 0
}
```
---
## AES-CCM authenticated encryption
```javascript
import sjcl from 'sjcl'
function encryptSJCL(plaintext: string, passphrase: string): string {
// sjcl.encrypt handles: PBKDF2 key derivation + AES-CCM + random IV + MAC
const encrypted = sjcl.encrypt(passphrase, plaintext, {
ks: 256, // AES key size: 128 | 192 | 256
ts: 128, // authentication tag size: 64 | 96 | 128 bits
iter: 100_000, // PBKDF2 iterations
mode: 'ccm', // ccm | gcm | ocb2
})
return encrypted // JSON string with iv, salt, ct, adata, mac
}
function decryptSJCL(encrypted: string, passphrase: string): string {
try {
return sjcl.decrypt(passphrase, encrypted)
} catch (e) {
throw new Error('[sjcl] decryption failed — wrong passphrase or tampered data')
}
}
```
---
## Cryptographic random bytes
```javascript
// SJCL PRNG (seeded from system entropy via window.crypto or a custom entropy function)
function secureRandom(bytes: number): string {
const wordCount = Math.ceil(bytes / 4)
const words = sjcl.random.randomWords(wordCount, 10) // paranoia level 10
return sjcl.codec.hex.fromBits(words).slice(0, bytes * 2)
}
// Session nonce
const nonce = secureRandom(16) // 32-char hex = 128-bit nonce
```
---
## PBKDF2 key derivation
```javascript
function deriveKeySJCL(passphrase: string, saltHex: string, iterations = 100_000): string {
const salt = sjcl.codec.hex.toBits(saltHex)
const key = sjcl.misc.pbkdf2(passphrase, salt, iterations, 256)
return sjcl.codec.hex.fromBits(key)
}
```
---
## SHA-256 / HMAC
```javascript
const hash = sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash('data'))
const key = sjcl.codec.utf8String.toBits(process.env.HMAC_KEY!)
const mac = sjcl.codec.hex.fromBits(new sjcl.misc.hmac(key).encrypt('message'))
```
---
## Anti-Fake-Pass Checklist
```
❌ sjcl.random.randomWords without seeding → throws on missing entropy in Node.js (use node-crypto seed)
❌ sjcl.encrypt paranoia < 6 → low entropy tolerance warning; use 8-10 for production
❌ Comparing MAC tags with === → timing attack; use constantTimeEqual above
❌ AES-CCM nonce reused → catastrophic, breaks authentication (SJCL uses random IV by default)
❌ sjcl in browser vs Node.js → window.crypto auto-seed in browser, must manually add entropy in Node
❌ sjcl output is JSON object — stringify before storing, parse before decrypting
```
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.