2016-09-18 1 views
3

Node.js에서 signing + verifying에 다음 예제를 사용하고 있습니다 : https://github.com/nodejs/node-v0.x-archive/issues/6904. 확인은 Node.js에서 성공하지만 WebCrypto에서는 실패합니다. 마찬가지로 WebCrypto를 사용하여 서명 한 메시지는 Node.js에서 확인하지 못합니다.Node.js와 WebCrypto 사이의 ECDSA 서명이 호환되지 않는 것으로 보입니까?

다음은 WebCrypto-https://jsfiddle.net/aj49e8sj/을 사용하여 Node.js 스크립트에서 생성 된 서명을 확인하는 데 사용한 코드입니다. 크롬 54.0.2840.27와 파이어 폭스 대신 SHA-1의 SHA-256을 사용하여 유사한 문제와 48.0.2

// From https://github.com/nodejs/node-v0.x-archive/issues/6904 
var keys = { 
    priv: '-----BEGIN EC PRIVATE KEY-----\n' + 
     'MHcCAQEEIF+jnWY1D5kbVYDNvxxo/Y+ku2uJPDwS0r/VuPZQrjjVoAoGCCqGSM49\n' + 
     'AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2\n' + 
     'pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' + 
     '-----END EC PRIVATE KEY-----\n', 
    pub: '-----BEGIN PUBLIC KEY-----\n' + 
     'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNh\n' + 
     'B8i3mXyIMq704m2m52FdfKZ2pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' + 
     '-----END PUBLIC KEY-----\n' 
}; 
var message = (new TextEncoder('UTF-8')).encode('hello'); 

// Algorithm used in Node.js script is ecdsa-with-SHA1, key generated with prime256v1 
var algorithm = { 
    name: 'ECDSA', 
    namedCurve: 'P-256', 
    hash: { 
     name: 'SHA-1' 
    } 
}; 

// Signature from obtained via above Node.js script 
var sig64 = 'MEUCIQDkAtiomagyHFi7dNfxMrzx/U0Gk/ZhmwCqaL3TimvlswIgPgeDqgZNqfR5/FZZASYsczUAhGSXjuycLhWnvk20qKc='; 

// Decode base64 string into ArrayBuffer 
var b64Decode = (str) => Uint8Array.from(atob(str), x => x.charCodeAt(0)); 

// Get base64 string from public key 
const key64 = keys.pub.split('\n') 
    .filter(x => x.length > 0 && !x.startsWith('-----')) 
    .join(''); 

// Convert to buffers 
var sig = b64Decode(sig64); 
var keySpki = b64Decode(key64); 

// Import and verify 
// Want 'Verification result: true' but will get 'false' 
var importKey = crypto.subtle.importKey('spki', keySpki, algorithm, true, ['verify']) 
    .then(key => crypto.subtle.verify(algorithm, key, sig, message)) 
    .then(result => console.log('Verification result: ' + result)); 

관련 질문 모두에서 테스트 : 나는 확인했습니다

Generating ECDSA signature with Node.js/crypto :

  • Node.js 키를 해독하고 WebCrypto를 통해 생성 된 키와 동일한 OID를 가지고 있는지 확인했습니다. 이것은 올바른 곡선을 사용하고 있음을 나타냅니다.
  • SHA-1은 두 위치 모두에서 사용할 해시로 명시 적으로 식별됩니다.
  • ECDSA는 Node.js와 WebCrypto에서 명시 적으로 식별됩니다.

Node.js에서받은 서명을 성공적으로 확인할 수있는 방법과 반대의 경우 - WebCrypto에서 생성 한 Node.js의 서명을 확인 하시겠습니까? 아니면 표준의 구현이 서로 호환되지 않는 방식으로 미묘하게 다릅니 까?

편집 :

  • WebCrypto 서명 (64 바이트) + uTaUWTfF AjN3aPj0b5Z2d1HybUEpV/PHV/P9RtfKaGXtcYnbgfO43IRg46rznG3/WnWwJ2sV6mPOEnEPR0vWw ==
  • Node.js를 서명 (71 바이트) MEUCIQDkAtiomagyHFi7dNfxMrzx/U0Gk/ZhmwCqaL3TimvlswIgPgeDqgZNqfR5/FZZASYsczUAhGSXjuycLhWnvk20qKc =

확인 된 Node.js 서명은 DER로 인코딩되고 WebCrypto 서명은 그렇지 않습니다.

답변

1

이러한 라이브러리 중 하나를 사용하지 않았기 때문에 확실하게 말할 수는 없지만 서명에 대해 동일한 인코딩 유형을 사용하지 않을 수도 있습니다. DSA/ECDSA의 경우 두 가지 기본 형식 인 IEEE P1363 (Windows에서 사용)과 DER (OpenSSL에서 사용)이 있습니다.

"Windows"형식은 DSA의 경우 Q로, ECDSA의 경우 P로 결정됩니다 (Windows는 Char-2를 지원하지 않지만 Char- 2의 경우 ECDSA의 경우 M 일 것임))). 그런 다음 rs 두 개가 길이가 될 때까지 0으로 왼쪽 패딩됩니다.이 시퀀스로서 DER의 규칙에 따라 인코딩되는 "은 OpenSSL"포맷

// r 
000305 
// s 
810522 

(INTEGER : 너무 작은에서

r = 0x305과는 sizeof와 s = 0x810522 (Q) 3 바이트되는 법적 예 될 (R)은, INTEGER (S)), 보이는 콤팩트

// SEQUENCE 
30 
    // (length of payload) 
    0A 
    // INTEGER(r) 
    02 
    // (length of payload) 
    02 
    // note the leading 0x00 is omitted 
    0305 
    // INTEGER(s) 
    02 
    // (length of payload) 
    04 
    // Since INTEGER is a signed type, but this represented a positive number, 
    // a 0x00 has to be inserted to keep the sign bit clear. 
    00810522 

또는 같은

  • 무선 ndows : 000305810522
  • 은 OpenSSL : 300A02020305020400810522

은 "윈도우"형식에도 항상, 항상 같은 길이입니다. "OpenSSL"형식은 일반적으로 약 6 바이트 더 크지 만 중간에 바이트를 얻거나 잃을 수 있습니다. 그래서 때로는 심지어 때로는 이상합니다.

sig64 값을 Base64로 디코딩하면 DER 인코딩을 사용하는 것으로 나타납니다. WebCrypto로 몇 개의 서명을 생성하십시오. 어떤 것이라도 0x30으로 시작하지 않으면 IEEE/DER 문제가 발생합니다.

+0

바로 돈! Node.js는 OpenSSL을 사용하므로 해당면의 DER 인코딩이 의미가 있습니다. WebCrypto 사양에 따르면 결과는 r이며 연결됩니다 (https://www.w3.org/TR/WebCryptoAPI/#ecdsa-operations). – SiNiquity

관련 문제