远程提取 (r,s) 和验证 ECDSA 签名
Extracting (r,s) and Verifying ECDSA signature remotely
我正在尝试使用 java 客户端对内容进行签名,然后在服务器 (nodejs) 上对其进行验证。我的客户端签名函数使用 ECDSA 和 returns a byte[]
。我可以访问服务器上包含 publicKey
的 x
和 y
坐标值。
public static byte[] sign(String plainText, PrivateKey privateKey) throws Exception {
java.security.Signature dsa = java.security.Signature.getInstance("SHA1withECDSA");
dsa.initSign(privateKey);
dsa.update(plainText.getBytes(UTF_8));
return dsa.sign();
}
是否可以找到构成签名的 r
和 s
值?如何将从上面获得的 byte[]
转换为 (r,s)
对或 DER-encoded signature
作为十六进制?在 node
服务器端,我使用 elliptic
进行签名验证。
编辑:
谢谢 Dave 的评论,我正在使用 methods indicated in this SO answer:
public static BigInteger extractR(byte[] signature) throws Exception {
int startR = (signature[1] & 0x80) != 0 ? 3 : 2;
int lengthR = signature[startR + 1];
return new BigInteger(Arrays.copyOfRange(signature, startR + 2, startR + 2 + lengthR));
}
public static BigInteger extractS(byte[] signature) throws Exception {
int startR = (signature[1] & 0x80) != 0 ? 3 : 2;
int lengthR = signature[startR + 1];
int startS = startR + 2 + lengthR;
int lengthS = signature[startS + 1];
return new BigInteger(Arrays.copyOfRange(signature, startS + 2, startS + 2 + lengthS));
}
知道 x
、y
、r
和 s
值,我正在尝试在节点服务器上验证消息 this is a test string
。
Message : this is a test string
Curve Parameters: secp256k1
Public Key:
X : 52552626316292256179275635993655485173638967401615704770864787021340356427096
Y : 115577290317206876914379725139810202736866562857077399175416156471449711434272
Signature details:
R : [0, -63, -80, -50, -87, -56, 93, 19, 82, 46, 51, 14, -75, 103, 115, 126, 21, 94, 43, 102, -21, -86, -29, -5, 25, 14, -6, -116, 120, -54, -66, 2, -78]
S : [0, -40, -119, 77, -14, 113, -105, -117, 93, 70, -107, -3, 63, 12, 77, -48, 59, -47, -7, -126, -60, -109, 95, -6, -66, -120, -8, -103, 122, 40, 24, -31, 89]
为了使用 elliptic
模块进行验证,我有以下内容
var EC_Instance = new EC();
var signature = {
r : new Buffer([0, -63, ..., 2, -78]),
s : new Buffer([0, -40, ..., -31, 89])
};
var x = "52552626316292256179275635993655485173638967401615704770864787021340356427096";
var y = "115577290317206876914379725139810202736866562857077399175416156471449711434272";
EC_Instance.importPublicKey(x, y); // calls ec.keyFromPublic(pub, 'hex')
var verification_true = EC_Instance.verify("this is a test string", signature);
而 EC_Instance
是 class 的对象,包含以下内容:
constructor() {
// Require the elliptic library for curve cryptography
var EC = require('elliptic').ec;
var ec = new EC('secp256k1');
this.ec = ec;
}
importPublicKey(x, y) {
var pub = { x: x.toString('hex'), y: y.toString('hex') };
var key = this.ec.keyFromPublic(pub, 'hex');
this.key = key;
return key;
}
verify(message, signature) {
return this.key.verify(message, signature);
}
可能是哈希函数。 SHA-1 不应再用于签名操作。
我推测 node.js 代码使用了 SHA-256 哈希方法,尽管用当前文档几乎不可能验证这一点(甚至几乎没有提到哈希)。
请注意,对于任何签名,哈希都是一个配置参数;它应该(并且对于 EC,它不能,至少在没有实际验证的情况下)由签名本身确定。
我正在尝试使用 java 客户端对内容进行签名,然后在服务器 (nodejs) 上对其进行验证。我的客户端签名函数使用 ECDSA 和 returns a byte[]
。我可以访问服务器上包含 publicKey
的 x
和 y
坐标值。
public static byte[] sign(String plainText, PrivateKey privateKey) throws Exception {
java.security.Signature dsa = java.security.Signature.getInstance("SHA1withECDSA");
dsa.initSign(privateKey);
dsa.update(plainText.getBytes(UTF_8));
return dsa.sign();
}
是否可以找到构成签名的 r
和 s
值?如何将从上面获得的 byte[]
转换为 (r,s)
对或 DER-encoded signature
作为十六进制?在 node
服务器端,我使用 elliptic
进行签名验证。
编辑:
谢谢 Dave 的评论,我正在使用 methods indicated in this SO answer:
public static BigInteger extractR(byte[] signature) throws Exception {
int startR = (signature[1] & 0x80) != 0 ? 3 : 2;
int lengthR = signature[startR + 1];
return new BigInteger(Arrays.copyOfRange(signature, startR + 2, startR + 2 + lengthR));
}
public static BigInteger extractS(byte[] signature) throws Exception {
int startR = (signature[1] & 0x80) != 0 ? 3 : 2;
int lengthR = signature[startR + 1];
int startS = startR + 2 + lengthR;
int lengthS = signature[startS + 1];
return new BigInteger(Arrays.copyOfRange(signature, startS + 2, startS + 2 + lengthS));
}
知道 x
、y
、r
和 s
值,我正在尝试在节点服务器上验证消息 this is a test string
。
Message : this is a test string
Curve Parameters: secp256k1
Public Key:
X : 52552626316292256179275635993655485173638967401615704770864787021340356427096
Y : 115577290317206876914379725139810202736866562857077399175416156471449711434272
Signature details:
R : [0, -63, -80, -50, -87, -56, 93, 19, 82, 46, 51, 14, -75, 103, 115, 126, 21, 94, 43, 102, -21, -86, -29, -5, 25, 14, -6, -116, 120, -54, -66, 2, -78]
S : [0, -40, -119, 77, -14, 113, -105, -117, 93, 70, -107, -3, 63, 12, 77, -48, 59, -47, -7, -126, -60, -109, 95, -6, -66, -120, -8, -103, 122, 40, 24, -31, 89]
为了使用 elliptic
模块进行验证,我有以下内容
var EC_Instance = new EC();
var signature = {
r : new Buffer([0, -63, ..., 2, -78]),
s : new Buffer([0, -40, ..., -31, 89])
};
var x = "52552626316292256179275635993655485173638967401615704770864787021340356427096";
var y = "115577290317206876914379725139810202736866562857077399175416156471449711434272";
EC_Instance.importPublicKey(x, y); // calls ec.keyFromPublic(pub, 'hex')
var verification_true = EC_Instance.verify("this is a test string", signature);
而 EC_Instance
是 class 的对象,包含以下内容:
constructor() {
// Require the elliptic library for curve cryptography
var EC = require('elliptic').ec;
var ec = new EC('secp256k1');
this.ec = ec;
}
importPublicKey(x, y) {
var pub = { x: x.toString('hex'), y: y.toString('hex') };
var key = this.ec.keyFromPublic(pub, 'hex');
this.key = key;
return key;
}
verify(message, signature) {
return this.key.verify(message, signature);
}
可能是哈希函数。 SHA-1 不应再用于签名操作。
我推测 node.js 代码使用了 SHA-256 哈希方法,尽管用当前文档几乎不可能验证这一点(甚至几乎没有提到哈希)。
请注意,对于任何签名,哈希都是一个配置参数;它应该(并且对于 EC,它不能,至少在没有实际验证的情况下)由签名本身确定。