Transactions
SECP256K1 有問題的數字簽名
我正在嘗試測試 TestNet3,並且我有一個使用 Java 加密庫生成的密鑰對。
私鑰是
23F847360E1EB348A212F443C633058080A8EB9F05AD132F8B82D51FE672EADD
,公鑰是044C8478229D9A139803AB0889617ECB6421191F3D891D0817D6A6CFD43BCBAA206FA9CE781E1C48764D8D1D0CE58DC6DE76C1B5F97CBCB5C9F01960DEAD3E192F
壓縮後的形式024C8478229D9A139803AB0889617ECB6421191F3D891D0817D6A6CFD43BCBAA20
。我導出了一個測試網地址,
msmVKMjAz7UdJSfkpvv3z4RMbt7pxocqZw
並決定使用它來簽署C46A8842187BB3642463B020D63462800FFB45791284404A965EF027D9F3B473
使用SHA256withECDSA
模式的交易雜湊。生成以下 R 和 S 作為簽名:
Component R: 038646375A34E4DA028B44362D1745870D019782245EF094AA788D17FD69F1D3 Component S: 00F29287B9A8913A9D751ECB33B32EEEB5614BAA32CF714811E29AE07F0886D4E7
我的簽名程式碼使用 BouncyCastle 作為 Java JCE 提供程序,如下所示:
System.out.println("BC Sign Begin"); System.out.println("============="); X9ECParameters CURVE_PARAMS = CustomNamedCurves.getByName("secp256k1"); ECDomainParameters CURVE = new ECDomainParameters(CURVE_PARAMS.getCurve(), CURVE_PARAMS.getG(), CURVE_PARAMS.getN(), CURVE_PARAMS.getH()); ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest())); ECPrivateKeyParameters privKey1 = new ECPrivateKeyParameters(((ECPrivateKey) keys[0]).getS(), CURVE); System.out.println("Curve A Coefficient (a): " + privKey1.getParameters().getCurve().getA().toBigInteger().toString(16)); System.out.println("Curve B Coefficient (b): " + privKey1.getParameters().getCurve().getB().toBigInteger().toString(16)); System.out.println("Curve G Generator X (Gx): " + privKey1.getParameters().getG().getAffineXCoord().toBigInteger().toString(16)); System.out.println("Curve G Generator Y (Gy): " + privKey1.getParameters().getG().getAffineYCoord().toBigInteger().toString(16)); System.out.println("Curve Order (n): " + privKey1.getParameters().getCurve().getOrder().toString(16)); System.out.println("Curve Cofactor (h): " + privKey1.getParameters().getCurve().getCofactor().toString(16)); System.out.println("Private Key In Use: " + ((ECPrivateKey) keys[0]).getS().toString(16)); signer.init(true, privKey1); BigInteger[] components = signer.generateSignature(input1); System.out.println("Component R: " + BinUtils.toHexString(components[0].toByteArray())); System.out.println("Component S: " + BinUtils.toHexString(components[1].toByteArray())); String compStrs = BinUtils.toHexString(components[0].toByteArray()) + "+" + BinUtils.toHexString(components[1].toByteArray()); System.out.println("Components String: " + compStrs);
輸出:
BC Sign Begin ============= Curve A Coefficient (a): 0 Curve B Coefficient (b): 7 Curve G Generator X (Gx): 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 Curve G Generator Y (Gy): 483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 Curve Order (n): fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 Curve Cofactor (h): 1 Private Key In Use: 23f847360e1eb348a212f443c633058080a8eb9f05ad132f8b82d51fe672eadd Component R: 038646375A34E4DA028B44362D1745870D019782245EF094AA788D17FD69F1D3 Component S: 00F29287B9A8913A9D751ECB33B32EEEB5614BAA32CF714811E29AE07F0886D4E7 Components String: 038646375A34E4DA028B44362D1745870D019782245EF094AA788D17FD69F1D3+00F29287B9A8913A9D751ECB33B32EEEB5614BAA32CF714811E29AE07F0886D4E7 =============
當我使用 BitcoinJ 將我的交易傳輸到 TestNet 時,我收到以下錯誤:
org.bitcoinj.core.ScriptException: Script resulted in a non-true stack: [] at org.bitcoinj.script.Script.correctlySpends(Script.java:1606) at java.lang.Thread.run(Thread.java:744) Hit an exception when trying to approve: java.util.concurrent.ExecutionException: org.bitcoinj.core.RejectedTransactionException: Reject: tx e374f230fe59b91ff88cc81768c10cb0d3b651079383da4dcfa4ef54372dcbd7 for reason 'mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation)' (16) at com.google.common.util.concurrent.AbstractFuture$Sync.getValue(AbstractFuture.java:299) at com.google.common.util.concurrent.AbstractFuture$Sync.get(AbstractFuture.java:286) at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:116) Caused by: org.bitcoinj.core.RejectedTransactionException: Reject: tx e374f230fe59b91ff88cc81768c10cb0d3b651079383da4dcfa4ef54372dcbd7 for reason 'mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation)' (16) at org.bitcoinj.core.TransactionBroadcast$2.onPreMessageReceived(TransactionBroadcast.java:102) at org.bitcoinj.core.Peer.processMessage(Peer.java:461) at org.bitcoinj.core.PeerSocketHandler.receiveBytes(PeerSocketHandler.java:184) at org.bitcoinj.net.ConnectionHandler.handleKey(ConnectionHandler.java:223) at org.bitcoinj.net.NioClientManager.handleKey(NioClientManager.java:86) at org.bitcoinj.net.NioClientManager.run(NioClientManager.java:122) at com.google.common.util.concurrent.AbstractExecutionThreadService$1$2.run(AbstractExecutionThreadService.java:60) at com.google.common.util.concurrent.Callables$3.run(Callables.java:95) at org.bitcoinj.utils.ContextPropagatingThreadFactory$1.run(ContextPropagatingThreadFactory.java:49) ... 1 more
您的壓縮公鑰是錯誤的。應該是
034c8478229d9a139803ab0889617ecb6421191f3d891d0817d6a6cfd43bcbaa20
。你是如何建造它的?