0

Я хочу проверить подписанное CMS сообщение с API веб-скрипта JavaScript. Сообщение является частью ответа временной метки в соответствии с RFC 3161.Не удалось проверить подписанное CMS сообщение с API webcrypto

Wireshark display

Итак, я беру подпись, содержание (от encapContentInfo) и открытый ключ и передать его в следующей функции, которая импортирует ключ и проверяет подпись:

function verify(signature, data, publicKey, callback) { 

    console.log("pubkey: " + publicKey); 
    console.log("data: " + data); 
    console.log("signature: " + signature); 

    crypto.subtle.importKey(
    "spki", 
    new Uint8Array(hexToArray(publicKey)), 
    { 
     name: "RSASSA-PKCS1-v1_5", 
     hash: {name: "SHA-1"} 
    }, 
    false, 
    ["verify"] 
    ) 
    .then(function(publicKey){ 

     console.log(publicKey); 

     crypto.subtle.verify(
     { 
      name: "RSASSA-PKCS1-v1_5", 
      hash: {name: "SHA-1"} 
     }, 
     publicKey, 
     new Uint8Array(hexToArray(signature)), 
     new Uint8Array(hexToArray(data)) 
     ) 
     .then(function(isvalid){ 
      console.log("valid: " + isvalid); 
     }) 
     .catch(function(err){ 
      throw(err); 
     }); 

    }) 
    .catch(function(err){ 
     throw(err); 
    }); 
} 

выход является следующее:

pubkey: 30820122300d06092a864886f70d01010105000382010f003082010a0282010100a9ac33b296da7177999d464f47aa4a40d57d58dcfd93beae68913ab75cb77fe36c4b52b3b55a53cce10f70880a81aba4ffdc1d4826fe645cbabcd1e0b4eceff702f6fb378670128eadbe39a4a9e484c1d01f95fcfcbd44ca091dcc344e0356ca8967f54f7f6acc0dd5af8c1a4f77003fe01c3b98d6611d52b3fe432962544e142cc6f99163ccb7798bb8d4aea948d0cd6f72b740915b87ca2824ac9ec958ab0e5eacb36a7a66be091e826f862849026aa911e3b1a84487f6654aad7f3be4d1d9d312b2f9fcd7c69836ae893060393a47b310a6a4b03eeea6c8659df57782fa75855007d5ffb622ff8d229edd57c0771149b7fc827780fcde0c02f82bc2977d250203010001 
data: 306b020101060c2b0601040181ad21822c16013031300d0609608648016503040201050004201b14e43e38297d534d827e351c15347f9eebc973258c8b555c044de46c5a0f02021424e3f636950c119fb3ebdb289d60d7bc637f3bd9180f32303136303431393139333931395a 
signature: 7a65069868d97fb0ffcd53bca6b80daa671e1b0ac1a1d262ba2fba1525d0ca8e4998d4f49cba990f9a89c52003457ca1bbb037dee8e5e64c617af0c1ea72215b648477b052165810f4f6eb7f869ac19373b2aad1a2b5a809b8b758bdad540a5cd1f33d3c80870c7ae9c6db61dd7c7f8c346ee3c7aadc16f90ed87833a4ba771cbdc930a6dfb3fd16f5ab57de212deddc4d49c11ef825a8d996ba40e0e07c7c5788000d61169fe7512c97d29f7ff4b8ce2842e5b339dae5cef1eb517457b3e8b98bc887dda952b6346bd8345e5eb2cdd976fe5688d375551bc2a20cd7aafd1bbf6a9d102ad2a8dea620ad3ed6763f0841ec020dc1ad485ed1448ae5f5d511ef8f 
CryptoKey {} 
valid: false 

Как вы можете видеть, проверка не удается, но я уверен, что подпись действительна, поскольку этот сервер timestamp используется многими людьми.

Есть ли что-то не так с моей реализацией?

Я пытаюсь сделать это внутри расширения Firefox.

Редактировать: Кажется, что необходимо использовать значение DER поля signedAttrs, хешировать его и затем проверять с помощью сертификата.

ответ

0

Мне удалось сделать это самостоятельно: сначала вам нужно расшифровать подпись с помощью открытого ключа, чтобы получить объект ASN.1, содержащий дайджест сообщения.

например. openssl rsautl -inkey cert.pem -pubin -in signature -out out

message digest object

Тогда вы берете signedAttrs объект и заменить явный тег в начале (0xa0) с заданным тегом (0x31) из следующего предложения в RFC:

The IMPLICIT [0] tag in the signedAttrs is not used for the DER encoding, rather an EXPLICIT SET OF tag is used 

Затем вы вычисляете дайджест (с тем же алгоритмом, что и в digestAlgorithm в signerInfo) заданного объекта.

Два значения дайджеста совпадают, если подпись действительна.