我可以使用Javascript (window.crypto.subtle.verify)的标准库验证ECDSA /window.crypto.subtle.verify签名,但不能使用jsrsasign (KJUR.crypto)。我也曾直接尝试过“KJUR.crypto.ECDSA”课程,但也没有运气。
请参见下面这两个脚本方法,它们提供的结果不一样。有人能告诉我这个问题吗?
//function to convert HEX to Decimal - return Arraybuffer
function hexStringToUint8Array(hexString) {
if (hexString.length % 2 != 0)
throw "Invalid hexString";
var arrayBuffer = new Uint8Array(hexString.length / 2);
for (var i = 0; i < hexString.length; i += 2) {
var byteValue = parseInt(hexString.substr(i, 2), 16);
if (byteValue == NaN)
throw "Invalid hexString";
arrayBuffer[i / 2] = byteValue;
}
return arrayBuffer;
}
//function to convert Base64 to hex (8 bits formats)
function base64ToHex(str) {
const raw = atob(str);
let result = '';
for (let i = 0; i < raw.length; i++) {
const hex = raw.charCodeAt(i).toString(16);
result += (hex.length === 2 ? hex : '0' + hex);
}
return result;
}
//convert Base64 URL to Base64
function base64urlToBase64(base64url) {
base64url = base64url.toString();
return base64url
.replace(/\-/g, "+")
.replace(/_/g, "/");
}
//Define values
Base64URL_coordX = '2uYQAsY-bvzz7r7SL-tK2C0eySfYEf1blv91cnd_1G4';
Base64URL_coordY = 'S3j1vy2sbkExAYXumb3w1HMVH-4ztoHclVTwQd45Reg';
signature = 'ed0c2b2e56731511ce2cea1d7320cdbc39dbabca7f525ec5d646b7c11cb35d5846a1cb70c2a1d8480f5ef88b46d401ca78b18ccae9ae4e3934a6b8fe412f7b11';
dataHex = '48656c6c6f20386777696669'; // ='Hello 8gwifi'
////////////Verifying Method using standard javascript
var dataToVerify = hexStringToUint8Array(dataHex);
var SignatureToVerify = hexStringToUint8Array(signature);
window.crypto.subtle.importKey(
"jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
{ //this is an example jwk key, other key types are Uint8Array objects
kty: "EC",
crv: "P-256",
x: Base64URL_coordX, // expects x and y to be «base64url» encoded
y: Base64URL_coordY,
ext: true,
},
{ //these are the algorithm options
name: "ECDSA",
namedCurve: "P-256", //can be "P-256", "P-384", or "P-521"
},
false, //whether the key is extractable (i.e. can be used in exportKey)
["verify"] //"verify" for public key import, "sign" for private key imports
)
.then(function(publicKey){
window.crypto.subtle.verify(
{
name: "ECDSA",
hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
publicKey, //from generateKey or importKey above
SignatureToVerify, //ArrayBuffer of the signature
dataToVerify //ArrayBuffer of the data
)
.then(function(isvalid){
console.log('Signature valid1: ', isvalid);
})
.catch(function(err){
console.error(err);
});
});
////////////Verifying Method using KJUR
Hex_coordX = base64ToHex(base64urlToBase64(Base64URL_coordX));
Hex_coordY = base64ToHex(base64urlToBase64(Base64URL_coordY));
var XY = Hex_coordX.toString(16) + Hex_coordY.toString(16);
var sig = new KJUR.crypto.Signature({"alg": "SHA256withECDSA", "prov": "cryptojs/jsrsa"});
sig.init({xy: XY, curve: "secp256r1"});
sig.updateHex(dataHex);
var result = sig.verify(signature);
//Printing Verification
console.log('Signature valid2: ', result);
发布于 2022-01-02 21:05:37
它在对库的描述中说它是JCA风格。这可能意味着签名生成/验证功能具有ASN.1 / DER编码输入/输出。
这包括一个ASN.1序列(标签0x30),即内部两个整数的长度。这两个整数的有标签0x02和签名的r和s组件的整数值的长度。这些是大数,有符号整数(这意味着如果字节为0x00,则剥离字节;如果顶部字节为0x80或更高,则添加0x00 )。
就你而言,这将是:
r = ed0c2b2e56731511ce2cea1d7320cdbc39dbabca7f525ec5d646b7c11cb35d58
s = 46a1cb70c2a1d8480f5ef88b46d401ca78b18ccae9ae4e3934a6b8fe412f7b11
现在将这些转换为ASN.1:
ri = 02 21 00 ed0c2b2e56731511ce2cea1d7320cdbc39dbabca7f525ec5d646b7c11cb35d58
si = 02 20 46a1cb70c2a1d8480f5ef88b46d401ca78b18ccae9ae4e3934a6b8fe412f7b11
最后,添加该序列并添加上述的级联:
sig = 30 45 02 21 00 ed0c2b2e56731511ce2cea1d7320cdbc39dbabca7f525ec5d646b7c11cb35d58
02 20 46a1cb70c2a1d8480f5ef88b46d401ca78b18ccae9ae4e3934a6b8fe412f7b11
检查结果,例如这里。
但我想在你的情况下,打电话给concatSigToASN1Sig
会更快:P
https://stackoverflow.com/questions/70558358
复制相似问题