| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- /**
- * Relay 加密与安全工具
- */
- import crypto from 'crypto';
- const RSA_KEY_SIZE = 2048;
- export interface KeyPair {
- publicKey: string;
- privateKey: string;
- }
- export function generateKeyPair(): KeyPair {
- const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
- modulusLength: RSA_KEY_SIZE,
- publicKeyEncoding: { type: 'spki', format: 'pem' },
- privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
- });
- return { publicKey, privateKey };
- }
- export function encryptWithPublicKey(publicKeyPem: string, plaintext: string): string {
- const publicKey = crypto.createPublicKey(publicKeyPem);
- const aesKey = crypto.randomBytes(32);
- const iv = crypto.randomBytes(12);
- const cipher = crypto.createCipheriv('aes-256-gcm', aesKey, iv);
- const ciphertext = Buffer.concat([
- cipher.update(Buffer.from(plaintext, 'utf8')),
- cipher.final(),
- ]);
- const wrappedKey = crypto.publicEncrypt(
- { key: publicKey, oaepHash: 'sha256' },
- aesKey,
- );
- const envelope = {
- v: 2,
- alg: 'RSA-OAEP-256+A256GCM',
- key: wrappedKey.toString('base64'),
- iv: iv.toString('base64'),
- tag: cipher.getAuthTag().toString('base64'),
- ciphertext: ciphertext.toString('base64'),
- };
- return `v2:${Buffer.from(JSON.stringify(envelope), 'utf8').toString('base64')}`;
- }
- export function hashApiSecret(secret: string): string {
- return crypto.createHmac('sha256', 'qiwei-relay-secret-salt').update(secret).digest('hex');
- }
- export function generateApiCredentials(): { apiKey: string; apiSecret: string } {
- return {
- apiKey: 'qk_' + crypto.randomBytes(16).toString('hex'),
- apiSecret: crypto.randomBytes(32).toString('hex'),
- };
- }
- export function generateRelaySecret(): string {
- return crypto.randomBytes(32).toString('hex');
- }
- export function verifyHmacSignature(secret: string, rawBody: string, signature: string): boolean {
- try {
- const expected = crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex');
- return timingSafeEqual(expected, signature);
- } catch {
- return false;
- }
- }
- export function verifyBearerToken(secret: string, authHeader: string | undefined): boolean {
- if (!authHeader) return false;
- const match = authHeader.match(/^Bearer\s+(.+)$/i);
- const provided = (match ? match[1] : authHeader).trim();
- if (!provided) return false;
- return timingSafeEqual(provided, secret);
- }
- function timingSafeEqual(a: string, b: string): boolean {
- if (a.length !== b.length) return false;
- try {
- return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));
- } catch {
- return false;
- }
- }
- export function sha256Hash(input: string): string {
- return crypto.createHash('sha256').update(input).digest('hex');
- }
|