60 lines
1.8 KiB
JavaScript
60 lines
1.8 KiB
JavaScript
'use strict';
|
||
|
||
/**
|
||
* JWT Ed25519 密钥加载(EdDSA)。
|
||
* 优先级:环境变量 PEM 明文 → 路径文件 → 默认 keys/ 目录。
|
||
*/
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const { createPrivateKey, createPublicKey } = require('crypto');
|
||
|
||
const DEFAULT_DIR = path.join(__dirname, '..', '..', 'keys');
|
||
const DEFAULT_PRIVATE = path.join(DEFAULT_DIR, 'jwt_ed25519_private.pem');
|
||
const DEFAULT_PUBLIC = path.join(DEFAULT_DIR, 'jwt_ed25519_public.pem');
|
||
|
||
function normalizePem(value) {
|
||
if (!value) return null;
|
||
return String(value).replace(/\\n/g, '\n').trim();
|
||
}
|
||
|
||
function readFileIfExists(filePath) {
|
||
if (!filePath || !fs.existsSync(filePath)) return null;
|
||
return fs.readFileSync(filePath, 'utf8');
|
||
}
|
||
|
||
function loadJwtKeys() {
|
||
const privatePem =
|
||
normalizePem(process.env.JWT_PRIVATE_KEY) ||
|
||
readFileIfExists(process.env.JWT_PRIVATE_KEY_PATH) ||
|
||
readFileIfExists(DEFAULT_PRIVATE);
|
||
const publicPem =
|
||
normalizePem(process.env.JWT_PUBLIC_KEY) ||
|
||
readFileIfExists(process.env.JWT_PUBLIC_KEY_PATH) ||
|
||
readFileIfExists(DEFAULT_PUBLIC);
|
||
|
||
if (!privatePem || !publicPem) {
|
||
throw new Error(
|
||
[
|
||
'JWT Ed25519 密钥未配置。请先生成密钥对:',
|
||
' node scripts/generate-jwt-keys.js',
|
||
'或设置 JWT_PRIVATE_KEY_PATH / JWT_PUBLIC_KEY_PATH(或 JWT_PRIVATE_KEY / JWT_PUBLIC_KEY)。',
|
||
].join('\n'),
|
||
);
|
||
}
|
||
|
||
const privateKey = createPrivateKey(privatePem);
|
||
const publicKey = createPublicKey(publicPem);
|
||
if (privateKey.asymmetricKeyType !== 'ed25519' || publicKey.asymmetricKeyType !== 'ed25519') {
|
||
throw new Error('JWT 密钥必须为 Ed25519(algorithm=EdDSA)');
|
||
}
|
||
|
||
return {
|
||
privateKey,
|
||
publicKey,
|
||
kid: process.env.JWT_KEY_ID || 'ed25519-1',
|
||
algorithm: 'EdDSA',
|
||
};
|
||
}
|
||
|
||
module.exports = { loadJwtKeys, DEFAULT_DIR, DEFAULT_PRIVATE, DEFAULT_PUBLIC };
|