遵循伟大的帖子[赎回一个原始交易一步一步的例子要求,我想出了下面的代码,但验证失败。
//pubkeyBytes,长度:65
//042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9
//数据长度:32
//30F10A6468B7D98257AF63FB40DFCF2CEFE991346FD37C67CF7B51FF8D404D3型
//签名字节,长度:71
//30450220587CE0CF0252E2DB3A7C3C91B355AA8F3385E128227CD8727C5F777877AD772022100EDC508B7C14891ED15AB38C687019D7EBAF5C12908CF21A83E8AE57E8C47E95C
ECPublicKey publicKey=(ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC,KeyBuilder.LENGTH_EC_FP_256,false);;
Secp256k1.setCommonCurveParameters(公钥);
publicKey.setW(pubkeyBytes,(short)0,(short)pubkeyBytes.length);
Signature eccSign=Signature.getInstance(Signature.ALG\u ECDSA\u SHA\u 256,false);
eccSign.init(公钥、签名、模式\验证);
布尔验证=eccSign.verify(data,(short)0,(short)data.length,
signatureBytes,(短)0,(短)signatureBytes.length
);
Assert.assertTrue(已验证);
断言最后失败。
已经被困了好几个小时了。我想不通。非常感谢您的帮助。谢谢。
交易验证
java
分享
改进这个问题
跟随
1月4日1:35编辑
九月151
55211银牌1212铜牌
11月28日20:30被问到
张永江
101
添加评论
2个答案
0
静态空隙试验
{
const MyByteArray pubkey(QByteArray::fromHex(“042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9”);
const MyByteArray signat(QByteArray::fromHex(“30450220587ce0cf0252e2db3a7c3c91b355aa8f3385e128227cd8727c5f77877ad772022100edc508b7c14891ed15ab38c687019d7ebaf5c12908cf21a83e8ae57e8c47e95c”);
const MyKey32摘要(QByteArray::fromHex(“30f10a6468b7d98257af63fb40dfcf2cefe991346fd37c67cf7b51ff8d4404d3”);
qDebug()<<(digest.verify(pubkey,signat)?”通过“:”失败“);
}
我的结果是::通过
签名对于摘要和公钥是正确的
在摘要中解码十六进制值和/或字节顺序的验证码可能有问题?
分享
改进这个答案
跟随
19年12月1日7点29分答复
阿马克林
630511金徽章1616银徽章3030铜徽章
添加评论
0
通常的问题是所使用的签名验证算法。比特币使用双SHA-256作为ECDSA的哈希算法,因此Z值是未签名事务的双SHA-256哈希。查看您正在使用的签名哈希算法:
签名算法ALG\u ECDSA\u SHA\u 256生成一个32字节的SHA-256摘要,并使用ECDSA和ECKey参数中定义的曲线对摘要进行签名/验证
您已经接受了Z值,但是只使用了一轮SHA-256再次对其进行哈希处理。您可以尝试传入一个只有一轮SHA-256哈希的前映像,然后让Signature对象处理第二轮,但是使用标准Java安全库的这种方法我运气不太好。为了在Java中完成比特币交易签名/验证,您需要(1)实现自己的ECDSA签名/验证,或者(2)使用BitcoinJ之类的库。以下是我在自己的ECPubKey类中的项目中使用的代码(请注意,我使用的是大量其他自定义代码,您将看到其中的方法调用,但这里不包括这些代码,但您将了解其中的要点):
/**
*@param preimage要验证的前映像
*@param signature一个ECDSA签名(R/S值对)
*@return此公钥是否用于生成给定前映像的签名
*/
公共布尔验证(字符串前映像、ECSignature){
String sigash=HashUtil.doubleSha256(前图像);
BigInteger z=新的BigInteger(1,ByteUtil.hex2bytes(sigash));
BigInteger r=signature.getR();
BigInteger s=signature.getS();
BigInteger sInv=s.modInverse(CurveParams.n);
BigInteger u1=z.multiply(sInv).mod(CurveParams.n);
BigInteger u2=r.multiply(sInv).mod(CurveParams.n);
ECPoint u1Point=ScalarMultiply.scalmult(曲线图.G,u1);
ECPoint u2Point=ScalarMultiply.scalmult(this.getPoint(),u2);
ECPoint sigPoint=ScalarMultiply.addPoint(u1Point,u2Point);
return r.compareTo(sigPoint.getAffineX().mod(CurveParams.n))==0;
}
该方法基本上是直接从ECDSA Wikipedia页面复制并翻译成Java。
分享
改进这个答案
跟随
19年12月31日21:07编辑