当前位置: 首页 > 知识库问答 >
问题:

远程提取(r,s)和验证ECDSA签名

庄欣然
2023-03-14

我尝试使用java客户端对内容进行签名,然后在服务器(nodejs)上进行验证。我的客户端签名函数使用ECDSA并返回一个< code>byte[]。我可以访问服务器上包含< code>publicKey的< code>x和< code>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();
}

是否可以找到构成签名的rs?如何将从上面获得的<code>字节〔〕对或<code>DER编码的签名

编辑:

谢谢戴夫的评论,我正在使用这个SO答案中指示的方法:

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));
}

知道xyrs值后,我正在尝试验证消息这是节点服务器上的测试字符串

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]

对于使用< code>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是包含以下内容的类的对象:

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);
}

共有1个答案

冯嘉珍
2023-03-14

可能是哈希函数。SHA-1不应再用于签名操作。

我认为对于节点来说。使用SHA-256哈希方法的js代码,尽管目前的文档几乎不可能验证这一点(甚至很少提到哈希)。

请注意——对于任何签名——哈希是一个配置参数;它应该(对于EC来说,它不能,至少在没有实际验证的情况下)从签名本身确定。

 类似资料:
  • 我正在写一段代码来检查签名 如果r和s是正的,我下面的代码可以工作,否则验证失败。 我的代码是 我的签名是从原始的r和s开始,以der格式创建的。请记住,如果r或s是负数,要在der格式中添加“00 ”,我还使用了BouncyCastle ANS1类 但是我仍然能够验证r和s是否为正,如果其中一个为负,我就不能验证(初始字节大于0x80) 我错过了什么? -----编辑----- 我已经创建了一个

  • 我使用Bouncy Castle/Java生成签名,因为它给出了两个带有R,S值的大整数。现在的要求是使用OpenSSL命令来验证。 例如:我要签名的消息是,运行上面的实用程序将返回R和S值,分隔符为'',在base64中编码为 现在在openssl端: 它无法验证,我被困住了--在openssl端不断得到“验证失败”的错误。

  • 我应该如何更改A方法?任何想法都是好的。提前谢谢。

  • 最近,我一直在尝试构建一个Java库来解释和验证NZ Covid传递。在签名验证之前(这个过程中稍微重要的一部分),我已经让代码变得更好或更坏。完整的代码可以在这里找到,但是仍然很粗糙。 验证器本身在这里可用,有一个配套测试。新冠通行证的技术规范在这里。至少有一个相关部分。 在与另一个开发人员合作后,我想我已经确定了解释提供的公钥。下面的代码(删除了调试输出)。公钥详细信息来自这里 该错误可能存在

  • 我想创建一个签名并使用openssl验证它。我想有我的签名的十六进制输出。 这是我的密码 我得到这个错误: 如果我在创建签名的过程中删除了-hex,它就可以工作了。

  • 我正在尝试在python中使用ECDSA验证比特币签名,但发现它非常困难,许多尝试已经失败了。 参数: 注意:我已经根据ECDSA的要求将签名从base64转换为hexstring。每当我试图验证它时,它会说: 预期64字节签名(128十六进制字符串),提供了65字节签名(130十六进制字符串) 我查看了许多关于ECDSA的stackoverflow问题,但没有一个答案与我的qs 100%相关。感