acp-ws
Version:
基于 WebSocket 的智能体通信库,提供智能体身份管理和实时通信功能
231 lines (230 loc) • 7.28 kB
JavaScript
var _a;
import { X509, KEYUTIL, KJUR } from 'jsrsasign';
import { CertAndKeyStore } from './datamanager';
function createSignedCertificate(aid = '') {
const { pubKeyObj, prvKeyObj } = KEYUTIL.generateKeypair("EC", "secp384r1");
const prvKeyPEM = KEYUTIL.getPEM(prvKeyObj, "PKCS8PRV");
const pubKeyPEM = KEYUTIL.getPEM(pubKeyObj);
const csrPEM = createCSR(aid, prvKeyPEM, pubKeyPEM);
return {
csrPEM,
prvKeyPEM,
pubKeyPEM
};
}
export async function createSignedCertificateAsync(aid = '') {
return await new Promise((resolve) => {
const cert = createSignedCertificate(aid);
resolve(cert);
});
}
export function isPemValid(certPem) {
// 解析为Date对象
function parseTime(timeStr) {
const year2 = parseInt(timeStr.substring(0, 2), 10);
const year = year2 >= 50 ? 1900 + year2 : 2000 + year2;
const month = timeStr.substring(2, 4);
const day = timeStr.substring(4, 6);
const hour = timeStr.substring(6, 8);
const minute = timeStr.substring(8, 10);
const second = timeStr.substring(10, 12);
return new Date(`${year}-${month}-${day}T${hour}:${minute}:${second}Z`);
}
// 解析证书
const x509 = new X509();
x509.readCertPEM(certPem);
const notBeforeStr = x509.getNotBefore();
const notAfterStr = x509.getNotAfter();
const notBefore = parseTime(notBeforeStr);
const notAfter = parseTime(notAfterStr);
const now = new Date();
const valid = now >= notBefore && now <= notAfter;
return valid;
}
export async function getPublicKeyPem(agentId) {
try {
const certPem = await CertAndKeyStore.getCertificate(agentId);
if (!certPem) {
throw new Error('证书不存在');
}
const publicKeyPem = await extractPublicKeyFromPem(certPem);
return {
publicKeyPem,
certPem
};
}
catch (error) {
console.error('获取公钥 PEM 格式失败:', error);
throw new Error('获取公钥失败');
}
}
// 检测运行环境
const isReactNative = (typeof global !== 'undefined' && global.HermesInternal !== undefined) ||
(typeof navigator !== 'undefined' && ((_a = navigator.userAgent) === null || _a === void 0 ? void 0 : _a.includes('ReactNative')));
/**
* 签名函数
*/
export async function signPrivate(nonce, privateKey) {
return new Promise((resolve, reject) => {
// 使用 setTimeout 确保不阻塞 UI 线程
setTimeout(async () => {
try {
let signature;
if (isReactNative) {
// React Native 环境下的优化处理
signature = await signInChunks(nonce, privateKey);
}
else {
// Web 环境可以直接处理
signature = await signDirect(nonce, privateKey);
}
resolve(signature);
}
catch (error) {
reject(error);
}
}, 0);
});
}
/**
* 分块处理签名,避免长时间阻塞UI
*/
async function signInChunks(nonce, privateKey) {
return new Promise((resolve, reject) => {
let step = 0;
let sig;
const processStep = () => {
try {
switch (step) {
case 0:
// 第一步:初始化签名对象
sig = new KJUR.crypto.Signature({ alg: "SHA256withECDSA" });
step++;
setTimeout(processStep, 0);
break;
case 1:
// 第二步:初始化私钥
sig.init(privateKey);
step++;
setTimeout(processStep, 0);
break;
case 2:
// 第三步:更新数据并签名
sig.updateString(nonce);
const signatureHex = sig.sign();
resolve(signatureHex);
break;
}
}
catch (error) {
reject(error);
}
};
processStep();
});
}
/**
* 直接签名处理(非 RN 环境)
*/
async function signDirect(nonce, privateKey) {
const sig = new KJUR.crypto.Signature({ alg: "SHA256withECDSA" });
sig.init(privateKey);
sig.updateString(nonce);
return sig.sign();
}
/**
* 公钥提取函数
*/
async function extractPublicKeyFromPem(certPem) {
return new Promise((resolve, reject) => {
setTimeout(async () => {
try {
let publicKey;
if (isReactNative) {
// React Native 环境下的分块处理
publicKey = await extractInChunks(certPem);
}
else {
// Web 环境直接处理
publicKey = await extractDirect(certPem);
}
resolve(publicKey);
}
catch (error) {
reject(error);
}
}, 0);
});
}
/**
* 分块提取公钥,避免长时间阻塞UI
*/
async function extractInChunks(certPem) {
return new Promise((resolve, reject) => {
let step = 0;
let x509;
let pubKeyObj;
const processStep = () => {
try {
switch (step) {
case 0:
// 第一步:初始化X509对象
x509 = new X509();
step++;
setTimeout(processStep, 0);
break;
case 1:
// 第二步:读取证书并提取公钥
x509.readCertPEM(certPem);
pubKeyObj = x509.getPublicKey();
const pubKeyPem = KEYUTIL.getPEM(pubKeyObj);
resolve(pubKeyPem);
break;
}
}
catch (error) {
reject(error);
}
};
processStep();
});
}
/**
* 直接提取公钥(非 RN 环境)
*/
async function extractDirect(certPem) {
const x509 = new X509();
x509.readCertPEM(certPem);
const pubKeyObj = x509.getPublicKey();
const pubKeyPem = KEYUTIL.getPEM(pubKeyObj);
return pubKeyPem;
}
/**
* 预加载 jsrsasign 模块
*/
export async function preloadCrypto() {
try {
// 预加载 jsrsasign 模块
require('jsrsasign');
}
catch (error) {
console.warn('Crypto preload failed:', error);
}
}
function createCSR(commonName, prvKeyPEM, pubKeyPEM) {
const csr = new KJUR.asn1.csr.CertificationRequest({
subject: {
str: `/C=CN/ST=SomeState/L=SomeCity/O=SomeOrganization/CN=${commonName}`
},
sbjpubkey: pubKeyPEM,
sbjprvkey: prvKeyPEM,
sigalg: "SHA256withECDSA",
extreq: [
{
extname: "basicConstraints",
}
]
});
const csrPEM = csr.getPEM();
return csrPEM;
}