验证 pycryptodome 在 WEB Crypto 中创建的数字签名 API
Verifying digital signature created by pycryptodome in WEB Crypto API
我正在使用 RSA 对 SHA512 哈希进行签名并将其保存到文件中。 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) 验证签名,但结果也是错误的。
我哪里错了?我试图比较哈希的字节值,它进入签名函数的输入,但实际上它是 python 上的 Crypto.Hash 对象。
Python代码中的sign
/verify
实现不会自动执行散列,即用户必须显式在签名前对数据进行散列。因此,在验证期间,用户必须根据数据的哈希值验证签名。
sign
/verify
implementation in the JavaScript-code performs hashing automatically, i.e. the user must not hash the data before signing. During verification, the user must therefore verify the signature against the data (and not against the hash of the data). The hash algorithm is specified in the key i.e. in generateKey
/importKey
使用 {hash: 'hash-algorithm'}。
发布的 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)
尝试使用此更改执行验证。
我正在使用 RSA 对 SHA512 哈希进行签名并将其保存到文件中。 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) 验证签名,但结果也是错误的。
我哪里错了?我试图比较哈希的字节值,它进入签名函数的输入,但实际上它是 python 上的 Crypto.Hash 对象。
Python代码中的sign
/verify
实现不会自动执行散列,即用户必须显式在签名前对数据进行散列。因此,在验证期间,用户必须根据数据的哈希值验证签名。
sign
/verify
implementation in the JavaScript-code performs hashing automatically, i.e. the user must not hash the data before signing. During verification, the user must therefore verify the signature against the data (and not against the hash of the data). The hash algorithm is specified in the key i.e. in generateKey
/importKey
使用 {hash: 'hash-algorithm'}。
发布的 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)
尝试使用此更改执行验证。