首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用xadesjs签署文档?

如何用xadesjs签署文档?
EN

Stack Overflow用户
提问于 2017-12-18 16:25:58
回答 1查看 1.7K关注 0票数 2

我有一个关于数字签名和xadesjs的问题。我正在用Node.js编写一个小型服务器,它应该用XAdES加密一个XML文件。我有一个PFX文件,我将其导出为PEM和PK8格式。一般的问题是,当我用keyPair生成xadesjs时,一切都很好。下面是一个例子:

代码语言:javascript
复制
// Generate RSA key pair
let privateKey, publicKey;
XAdES.Application.crypto.subtle.generateKey(
    {
        name: "RSASSA-PKCS1-v1_5",
        modulusLength: 1024, //can be 1024, 2048, or 4096,
        publicExponent: new Uint8Array([1, 0, 1]),
        hash: { name: "SHA-256" }, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
    },
    false, //whether the key is extractable (i.e. can be used in exportKey)
    ["sign", "verify"] //can be any combination of "sign" and "verify"
)
.then(function (keyPair) {
    privateKey = keyPair.privateKey;

    // Call sign function
    return SignXml(xmlString, privateKey, 
        { name: "RSASSA-PKCS1-v1_5", hash: { name: "SHA-256" } });
})
.then(function (signedDocument) {
    console.log("Signed document:\n\n", signedDocument);
    next(null, signedDocument);
})
.catch(function (e) {
    console.log(e);
    next(e, null);
});

但是,我一直在使用所有可能的组合来使importKey方法工作。例如,即使键位于PKCS8 (与OpenSSL一起导出)中,这也不起作用:

代码语言:javascript
复制
let key =  fs.readFileSync("key.pem");

XAdES.Application.crypto.subtle.importKey("pkcs8", key,
    {
        name: "RSASSA-PKCS1-v1_5",
        modulusLength: 2048, //can be 1024, 2048, or 4096,
        publicExponent: new Uint8Array([1, 0, 1]),
        hash: { name: "SHA-256" },
    },
    false, 
    ["sign"]
)
.then(function (privateKey) {
    // Call sign function
    return SignXml(xmlString, privateKey, 
         { name: "RSASSA-PKCS1-v1_5", hash: { name: "SHA-256" } });
})

我发现一个错误:

代码语言:javascript
复制
Error: ImportKey: Can not import key for pkcs8

我的主要目标是获得一个程序,在该程序中,我可以指定数字签名的路径,我的程序将导入密钥和证书,并最终使用它们对我的文件签名。如果一切都可以存储在PFX文件中,这将是很舒服的,但是如果您有任何解决方案,即使密钥和证书分别存储(PEM和PK8),我将非常感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-02 15:24:03

万一有人有同样的问题。下面是@pedrofb的答案的一个实现。

首先,我在pem npm软件包的帮助下获得了密钥和证书。然后删除页眉和页脚,并将键转换为ArrayBuffer:

代码语言:javascript
复制
const pfx = fs.readFileSync("cert.pfx");
pem.readPkcs12(pfx, { p12Password: "test123" }, (err: any, cert: any) => {
    if(err) return console.log(err);
    let privateKey = b64ToBinary(removePFXComments(cert.key));
    let certificate = removePFXComments(cert.cert);

下面是上面使用的两种方法的实现:

代码语言:javascript
复制
function removePFXComments(pem) {
    let lines = pem.split('\n');
    let encoded = '';
    for (let i = 0; i < lines.length; i++) {
        if (lines[i].trim().length > 0 &&
            lines[i].indexOf('-----BEGIN CERTIFICATE-----') < 0 &&
            lines[i].indexOf('-----END CERTIFICATE') < 0 &&
            lines[i].indexOf('-----BEGIN RSA PRIVATE KEY-----') < 0 &&
            lines[i].indexOf('-----BEGIN RSA PUBLIC KEY-----') < 0 &&
            lines[i].indexOf('-----BEGIN PUBLIC KEY-----') < 0 &&
            lines[i].indexOf('-----END PUBLIC KEY-----') < 0 &&
            lines[i].indexOf('-----BEGIN PRIVATE KEY-----') < 0 &&
            lines[i].indexOf('-----END PRIVATE KEY-----') < 0 &&
            lines[i].indexOf('-----END RSA PRIVATE KEY-----') < 0 &&
            lines[i].indexOf('-----END RSA PUBLIC KEY-----') < 0) {
            encoded += lines[i].trim();
        }
    }
    return encoded;
}

function b64ToBinary(base64) {
  let raw = atob(base64);
  let rawLength = raw.length;
  let array = new Uint8Array(new ArrayBuffer(rawLength));

  for(let i = 0; i < rawLength; i++) {
    array[i] = raw.charCodeAt(i);
  }
  return array;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47872508

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档