锯齿无效的批次或签名

我最近开始使用Hyperledger Sawtooth进行播放,并且无法在java上提交事务,而python代码似乎没问题。

我已经在这里编写了基于api文档的python代码,然后尝试在java中编写一个。 下面是java中的代码

import com.google.protobuf.ByteString; import com.mashape.unirest.http.Unirest; import sawtooth.sdk.processor.Utils; import sawtooth.sdk.protobuf.*; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.Signature; import java.security.spec.ECGenParameterSpec; public class BatchSender { public static void main(String[] args) throws Exception{ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); ECGenParameterSpec parameterSpec = new ECGenParameterSpec("secp256k1"); keyPairGenerator.initialize(parameterSpec); KeyPair keyPair = keyPairGenerator.generateKeyPair(); Signature ecdsaSign = Signature.getInstance("SHA256withECDSA"); ecdsaSign.initSign(keyPair.getPrivate()); byte[] publicKeyBytes = keyPair.getPublic().getEncoded(); String publicKeyHex = Utils.hash512(publicKeyBytes); ByteString publicKeyByteString = ByteString.copyFrom(new String(publicKeyBytes),"UTF-8"); String payload = "{'key':1, 'value':'value comes here'}"; String payloadBytes = Utils.hash512(payload.getBytes()); ByteString payloadByteString = ByteString.copyFrom(payload.getBytes()); TransactionHeader txnHeader = TransactionHeader.newBuilder(). setBatcherPubkeyBytes(publicKeyByteString). setFamilyName("plain_info"). setFamilyVersion("1.0"). addInputs("1cf1266e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7"). setNonce("1"). addOutputs("1cf1266e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7"). setPayloadEncoding("application/json"). setPayloadSha512(payloadBytes). setSignerPubkey(publicKeyHex).build(); ByteString txnHeaderBytes = txnHeader.toByteString(); ecdsaSign.update(txnHeaderBytes.toByteArray()); byte[] txnHeaderSignature = ecdsaSign.sign(); Transaction txn = Transaction.newBuilder().setHeader(txnHeaderBytes).setPayload(payloadByteString).setHeaderSignature(Utils.hash512(txnHeaderSignature)).build(); BatchHeader batchHeader = BatchHeader.newBuilder().setSignerPubkey(publicKeyHex).addTransactionIds(txn.getHeaderSignature()).build(); ByteString batchHeaderBytes = batchHeader.toByteString(); ecdsaSign.update(batchHeaderBytes.toByteArray()); byte[] batchHeaderSignature = ecdsaSign.sign(); Batch batch = Batch.newBuilder().setHeader(batchHeaderBytes).setHeaderSignature(Utils.hash512(batchHeaderSignature)).addTransactions(txn).build(); BatchList batchList = BatchList.newBuilder().addBatches( batch).build(); ByteString batchBytes = batchList.toByteString(); String serverResponse = Unirest.post("http://rest-api:8080/batches").header("Content-Type","application/octet-stream").body(batchBytes.toByteArray()).asString().getBody(); System.out.println(serverResponse); } } 

一旦我运行它,我就会得到它

 { "error": { "code": 30, "message": "The submitted BatchList was rejected by the validator. It was poorly formed, or has an invalid signature.", "title": "Submitted Batches Invalid" } } 

在docker工日志上,我可以看到

 sawtooth-validator-default | [2017-11-21 08:20:09.842 DEBUG interconnect] ServerThread receiving CLIENT_BATCH_SUBMIT_REQUEST message: 1242 bytes sawtooth-validator-default | [2017-11-21 08:20:09.844 DEBUG signature_verifier] batch failed signature validation: 30a2f4a24be3e624f5a35b17cb505b65cb8dd41600545c6dcfac7534205091552e171082922d4eb71f1bb186fe49163f349c604b631f64fa8f1cfea1c8bb2818 sawtooth-validator-default | [2017-11-21 08:20:09.844 DEBUG interconnect] ServerThread sending CLIENT_BATCH_SUBMIT_RESPONSE to b'50b094689ac14b39' 

我检查了密钥大小并validation了签名,看起来一切都好,但是,我无法找到为什么批次被拒绝…

以前任何人都有类似的锯齿响应错误? 是上面代码的批处理格式还是签名问题?

问题在于设置批头标题和事务标题签名。 那些不应该使用sha-512哈希值。 这些字节应编码为hex字符串。

使用apache-commons-codec库可以完成:

 import org.apache.commons.codec.binary.Hex; Transaction txn = Transaction.newBuilder() .setHeader(txnHeaderBytes) .setPayload(payloadByteString) .setHeaderSignature(Hex.encodeHexString(txnHeaderSignature)) .build(); 

Utils.sha512应仅用于有效负载字节。

Sawtooth Java SDK附带了一个Signing类,可以帮助生成私钥/公钥对和签名消息。

我修改了你的代码以使用指定的类,并包含了Boyd Johnson对一个工作示例的答案的更改(这是使用Sawtooth Java SDK 1.0版 ):

 import com.google.protobuf.ByteString; import com.mashape.unirest.http.Unirest; import com.mashape.unirest.http.exceptions.UnirestException; import org.bitcoinj.core.ECKey; import sawtooth.sdk.client.Signing; import sawtooth.sdk.processor.Utils; import sawtooth.sdk.protobuf.Batch; import sawtooth.sdk.protobuf.BatchHeader; import sawtooth.sdk.protobuf.BatchList; import sawtooth.sdk.protobuf.Transaction; import sawtooth.sdk.protobuf.TransactionHeader; import java.security.SecureRandom; public class BatchSender { public static void main(String []args) throws UnirestException { ECKey privateKey = Signing.generatePrivateKey(new SecureRandom()); String publicKey = Signing.getPublicKey(privateKey); ByteString publicKeyByteString = ByteString.copyFromUtf8(publicKey); String payload = "{'key':1, 'value':'value comes here'}"; String payloadBytes = Utils.hash512(payload.getBytes()); ByteString payloadByteString = ByteString.copyFrom(payload.getBytes()); TransactionHeader txnHeader = TransactionHeader.newBuilder() .setBatcherPublicKeyBytes(publicKeyByteString) .setSignerPublicKeyBytes(publicKeyByteString) .setFamilyName("plain_info") .setFamilyVersion("1.0") .addInputs("1cf1266e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7") .setNonce("1") .addOutputs("1cf1266e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7") .setPayloadSha512(payloadBytes) .setSignerPublicKey(publicKey) .build(); ByteString txnHeaderBytes = txnHeader.toByteString(); String txnHeaderSignature = Signing.sign(privateKey, txnHeaderBytes.toByteArray()); Transaction txn = Transaction.newBuilder() .setHeader(txnHeaderBytes) .setPayload(payloadByteString) .setHeaderSignature(txnHeaderSignature) .build(); BatchHeader batchHeader = BatchHeader.newBuilder() .setSignerPublicKey(publicKey) .addTransactionIds(txn.getHeaderSignature()) .build(); ByteString batchHeaderBytes = batchHeader.toByteString(); String batchHeaderSignature = Signing.sign(privateKey, batchHeaderBytes.toByteArray()); Batch batch = Batch.newBuilder() .setHeader(batchHeaderBytes) .setHeaderSignature(batchHeaderSignature) .addTransactions(txn) .build(); BatchList batchList = BatchList.newBuilder() .addBatches(batch) .build(); ByteString batchBytes = batchList.toByteString(); String serverResponse = Unirest.post("http://localhost:8008/batches") .header("Content-Type","application/octet-stream") .body(batchBytes.toByteArray()) .asString() .getBody(); System.out.println(serverResponse); } } 

我刚才有同样的问题。 就我而言,问题在于设置有效载荷数据。

请确保:

  • 您为PayloadByteArray创建了sha512哈希并将其传递给TransactionHeader创建
  • 您将PayloadByteArray传递给事务创建。

所以:

  • PayloadByteArray – >创建事务
  • sha512 PayloadByteArray的哈希 – > TransactionHeader创建
Interesting Posts