feat: scaffold Antonym fashion store
Anonymous Bitcoin-only fashion e-commerce with: - Vue 3 + Tailwind 4 frontend with glassmorphism dark/light design system - Express 5 + SQLite backend with BTCPay Server integration - Nostr identity (NIP-07/keypair) for anonymous purchase tracking - ChaCha20-Poly1305 encrypted shipping addresses - Admin panel with order/product/stock management - SVG logo splash animation with clip-path reveal - 5 seeded products across 4 categories Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
33
server/lib/crypto.ts
Normal file
33
server/lib/crypto.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import crypto from 'node:crypto'
|
||||
|
||||
const ALGORITHM = 'chacha20-poly1305'
|
||||
const NONCE_LENGTH = 12
|
||||
const TAG_LENGTH = 16
|
||||
|
||||
function getKey(): Buffer {
|
||||
const hex = process.env.ENCRYPTION_KEY
|
||||
if (!hex || hex.length !== 64) {
|
||||
throw new Error('ENCRYPTION_KEY must be a 64-character hex string (32 bytes)')
|
||||
}
|
||||
return Buffer.from(hex, 'hex')
|
||||
}
|
||||
|
||||
export function encrypt(plaintext: string): string {
|
||||
const key = getKey()
|
||||
const nonce = crypto.randomBytes(NONCE_LENGTH)
|
||||
const cipher = crypto.createCipheriv(ALGORITHM, key, nonce, { authTagLength: TAG_LENGTH })
|
||||
const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()])
|
||||
const tag = cipher.getAuthTag()
|
||||
return Buffer.concat([nonce, tag, encrypted]).toString('hex')
|
||||
}
|
||||
|
||||
export function decrypt(ciphertext: string): string {
|
||||
const key = getKey()
|
||||
const buf = Buffer.from(ciphertext, 'hex')
|
||||
const nonce = buf.subarray(0, NONCE_LENGTH)
|
||||
const tag = buf.subarray(NONCE_LENGTH, NONCE_LENGTH + TAG_LENGTH)
|
||||
const encrypted = buf.subarray(NONCE_LENGTH + TAG_LENGTH)
|
||||
const decipher = crypto.createDecipheriv(ALGORITHM, key, nonce, { authTagLength: TAG_LENGTH })
|
||||
decipher.setAuthTag(tag)
|
||||
return decipher.update(encrypted) + decipher.final('utf8')
|
||||
}
|
||||
Reference in New Issue
Block a user