2017-12-18 31 views
2

디지털 서명 및 xadesjs과 관련하여 문제가 있습니다. Node.js에 XAdES를 사용하여 XML 파일을 암호화해야하는 작은 서버를 작성했습니다. PFX 파일을 가지고 있는데 PEM과 PK8 형식으로 내 보냅니다. 일반적인 문제는 xadesjs으로 keyPair를 생성 할 때 모든 것이 잘 작동한다는 것입니다. 다음은 예입니다 :xadesjs에서 문서에 서명하는 방법은 무엇입니까?

// 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을 내 보낸) :

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" } }); 
}) 

내가 그 오류 얻을 :

Error: ImportKey: Can not import key for pkcs8 

내 주요 목표는 프로그램을 얻을하는 것입니다, 어디 디지털 서명의 경로를 지정할 수 있으며 내 프로그램은 키와 인증서를 가져오고 끝에는 내 파일에 서명합니다. 모든 것이 PFX 파일에 저장 될 수 있다면 편안 할 것입니다.하지만 솔루션이 있다면 키와 인증서가 따로 저장되어 있어도 (PEM 및 PK8) 감사하게 생각합니다.

+1

. 바이너리 ArrayBuffer로 가져와야합니다 :'----- BEGIN PRIVATE KEY -----'헤더와 풋터를 제거하고, 내용을 base64에서 바이너리로 변환하고, 결과를 char에서 ArrayBuffer로 변환합니다. pkcs8 키가 암호로도 보호되지 않았는지 확인하십시오 – pedrofb

+0

고마워요, 그 트릭을 했어! – losik123

답변

1

누구나 동일한 문제가있는 경우. 다음은 @pedrofb의 대답을 이용한 구현입니다.

먼저 pem npm 패키지의 도움으로 키와 인증서를받습니다. 그럼 난 머리글과 바닥 글을 제거하고 ArrayBuffer에 키를 변환 :

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); 

을 여기에 위의 두 가지 사용 방법의 구현이다 : 나는 당신이 PEM과 키를 읽고 생각

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; 
}