我正试图用SHA256withECDSA解码/编码一个签名。我有一个运行良好的Java代码:
public void verify() throws Exception {
Signature ecdsaVerify = Signature.getInstance("SHA256withECDSA"));
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode("your public key goes here"));
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
ecdsaVerify.initVerify(publicKey);
ecdsaVerify.update("All the webhook field values (only the values) concatenated together using a semicolon ;".getBytes("UTF-8"));
boolean result = ecdsaVerify.verify(Base64.getDecoder().decode("Signature to verify")); //Must return true
}
但我需要nodejs的这个解决方案。当我在nodejs中创建一个base64缓冲区时,它将得到与Java代码不同的结果。目前我使用的是密码‘s& jwa npm。
编辑:
这是我的nodejs代码:
var jwa = require("jwa");
const verifySignature = () => {
let public_key = Buffer.from("public key here", "base64");
let signature = Buffer.from("Signature_here", "base64");
let payload = "data here seperated by semicolon";
let ecdsa = jwa("ES256");
let verify = ecdsa.verify(payload, signature, public_key);
}
verifySignature();
发布于 2022-01-10 19:48:43
JWA实现了在JOSE中使用的算法,特别是对于ECDSA,它使用了在P1363中定义的签名格式(又名编码),它只包含连接在一起的固定长度R和S;参见https://datatracker.ietf.org/doc/html/rfc7518#section-3.4的步骤2和3。这不是大多数其他标准所使用的格式,尤其是Java,Java是由两个整数值组成的ASN.1 DER编码序列,它们都是带有标记和长度前缀的可变长度(all)。
您根本不需要JWA;内置的'crypto‘具有您需要的功能:
import java.security.KeyFactory;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class SO70655734 {
public static void main (String[] args) throws Exception {
String data = "some;test;data";
String pubkey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyOFORyCVCxX+W4QZevzH6skTbp2lVDtRLV0+7ypHjX26wFtSWSe4MTI0GZjIKDOAIT8KpbqH8HXI6Wo5S6/6hg==";
String sig = "MEQCICDLwztlKOXmQLuDJ0Hh96gGAT2/wsm2ymw3CDxSDnB3AiAK7eR8+C6g/zw5TmXUX0K/pV5kjIJTCieIkQXzH30WYA==";
Signature ecdsa = Signature.getInstance("SHA256withECDSA");
ecdsa.initVerify(KeyFactory.getInstance("EC").generatePublic(
new X509EncodedKeySpec(Base64.getDecoder().decode(pubkey)) ));
ecdsa.update(data.getBytes("UTF-8")); // or StandardCharsets.UTF_8
System.out.println(ecdsa.verify(Base64.getDecoder().decode(sig)));
}
}
-> true
const crypto = require('crypto');
const data = "some;test;data";
const pubkey = "-----BEGIN PUBLIC KEY-----\n"
+ "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyOFORyCVCxX+W4QZevzH6skTbp2lVDtRLV0+7ypHjX26wFtSWSe4MTI0GZjIKDOAIT8KpbqH8HXI6Wo5S6/6hg==\n"
+ "-----END PUBLIC KEY-----\n";
const sig = "MEQCICDLwztlKOXmQLuDJ0Hh96gGAT2/wsm2ymw3CDxSDnB3AiAK7eR8+C6g/zw5TmXUX0K/pV5kjIJTCieIkQXzH30WYA==";
var ecdsa = crypto.createVerify('SHA256');
ecdsa.update(data,'utf8');
console.log( ecdsa.verify(pubkey, sig,'base64') );
-> true
注意: nodejs的最新版本可以采用DER格式的公键(没有添加开始/结束行,而是将base64转换为二进制),但是我最方便的测试系统只有8.10.0,所以我采用了更兼容的老方法。
https://stackoverflow.com/questions/70655734
复制相似问题