37 lines
852 B
TypeScript
37 lines
852 B
TypeScript
import * as crypto from 'node:crypto';
|
|
|
|
/**
|
|
* Manages ACME replay nonces.
|
|
* Each nonce is single-use: consumed on verification, fresh one issued with every response.
|
|
*/
|
|
export class NonceManager {
|
|
private nonces = new Set<string>();
|
|
private nonceQueue: string[] = [];
|
|
private maxSize: number;
|
|
|
|
constructor(maxSize = 10000) {
|
|
this.maxSize = maxSize;
|
|
}
|
|
|
|
generate(): string {
|
|
const nonce = crypto.randomBytes(16).toString('base64url');
|
|
if (this.nonces.size >= this.maxSize) {
|
|
const oldest = this.nonceQueue.shift();
|
|
if (oldest) {
|
|
this.nonces.delete(oldest);
|
|
}
|
|
}
|
|
this.nonces.add(nonce);
|
|
this.nonceQueue.push(nonce);
|
|
return nonce;
|
|
}
|
|
|
|
consume(nonce: string): boolean {
|
|
if (this.nonces.has(nonce)) {
|
|
this.nonces.delete(nonce);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|