Проверка цифровой подписи, созданной pycryptodome в WEB Crypto API - PullRequest
1 голос
/ 30 сентября 2019

Я подписываю хэш SHA512 с помощью RSA и сохраняю его в файл. Хеш одинаков как на python, так и на javascript, но подпись не может быть проверена. Код Python:

from Cryptodome.Hash import SHA512
from Cryptodome.PublicKey import RSA
from Cryptodome.Signature import pkcs1_15

hash = SHA512.new(someByteArray)
#This is equal to digest generated in JavaScript
hashDigest = hashPDF.hexdigest()
pk = RSA.importKey(privateKey)
signature=pkcs1_15.new(pk).sign(hashPDF)
#Write signature to file
with open("storage/{0}.sig".format(hashDigest), 'wb+') as f:
        f.write(signature)

#Then JavaScript request occurs return content of saved signature in base64

from base64 import b64encode
from flask import jsonify
with open("storage/{0}.sig".format(pdfHashDigest), "rb") as f:
        sign = b64encode(f.read())
return jsonify({"sign":sign.decode("utf-8")})

JavaScript:

var hash=await crypto.subtle.digest('SHA-512', Uint8Array.from(atob(someBase64content), c => c.charCodeAt(0)))
//This is equal to python hashDigest
var hashDigest = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
var cryptoKey=await crypto.subtle.importKey('spki', this.pemToArrayBuffer(publicKey), {name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-512'}, false, ["verify"])
//Always false
var result=await crypto.subtle.verify("RSASSA-PKCS1-v1_5", cryptoKey, Uint8Array.from(atob(signature), c => c.charCodeAt(0)), hash)

Я пробовал разные способы преобразования подписи base64 в ArrayBuffer для использования в Web Crypto API: rfc4648.js, новый TextEncoder (), пользовательскийпреобразования в Uint8Array, но результат всегда ложный. Также я попытался проверить подпись, используя forge (https://github.com/digitalbazaar/forge), но результат также ложный.

Где я ошибаюсь? Я пытался сравнить байтовые значения хэша, которые идут на ввод функций подписи,но на самом деле это объект Crypto.Hash на python.

1 Ответ

1 голос
/ 01 октября 2019

Реализация sign / verify в Python-коде не выполняет автоматическое хеширование, т. Е. Пользователь должен явно хешировать данные перед подписанием. Поэтому при проверке пользователь должен проверить подпись по хешу данных.

Реализация sign / verify в JavaScript-коде выполняетхэширование автоматически, т.е. пользователь не должен хэшировать данные перед подписанием. Поэтому во время проверки пользователь должен проверить подпись по данным (и , а не по хешу данных). Алгоритм хеширования указан в ключе, т.е. в generateKey / importKey с использованием {hash: 'hash-алгоритма'}.

Ошибка вРазмещенный JavaScript-код вызывается проверкой подписи по хешу данных. Это не верно. Сигнатура должна быть проверена по данным, т.е. в JavaScript-коде следующие строки:

var hash=await crypto.subtle.digest('SHA-512', Uint8Array.from(atob(someBase64content), c => c.charCodeAt(0)))
...
var result=await crypto.subtle.verify("RSASSA-PKCS1-v1_5", cryptoKey, Uint8Array.from(atob(signature), c => c.charCodeAt(0)), hash)

должны быть заменены на

var data=Uint8Array.from(atob(someBase64content), c => c.charCodeAt(0));
...
var result=await crypto.subtle.verify("RSASSA-PKCS1-v1_5", cryptoKey, Uint8Array.from(atob(signature), c => c.charCodeAt(0)), data)

Попробуйте выполнить проверку с этим изменением.

...