Hyperledger Fabric Node.js SDK:脱机交易签名问题

问题描述 投票:1回答:1

我正在尝试遵循本教程:https://hyperledger.github.io/fabric-sdk-node/release-1.4/tutorial-sign-transaction-offline.html

我使用此指南创建了完整的Hyperledger Fabric网络:https://hyperledger-fabric-ca.readthedocs.io/en/latest/operations_guide.html

JavaScript SDK运行良好,我可以使用client.setUserContext()方法查询/调用事务。

[尝试脱机签署交易时,交易建议被同行拒绝,并显示以下响应:

{ Error: 2 UNKNOWN: access denied: channel [mychannel] creator org [org1]
      at Object.exports.createStatusError ([...]/node_modules/grpc/src/common.js:91:15)
      at Object.onReceiveStatus ([...]/node_modules/grpc/src/client_interceptors.js:1204:28)
      at InterceptingListener._callNext ([...]/node/node_modules/grpc/src/client_interceptors.js:568:42)
      at InterceptingListener.onReceiveStatus ([...]/node/node_modules/grpc/src/client_interceptors.js:618:8)
      at callback ([...]/node/node_modules/grpc/src/client_interceptors.js:845:24)
    code: 2,
    metadata: Metadata { _internal_repr: {} },
    details: 'access denied: channel [mychannel] creator org [org1]' }

在来自同行的日志中,我看到以下错误:

peer1-org1       | 2020-01-13 21:47:31.569 UTC [protoutils] ValidateProposalMessage -> WARN 078 channel [mychannel]: creator's signature over the proposal is not valid: The signature is invalid

我不明白为什么签名被拒绝。我认真遵循了本教程的所有步骤。这是完整的客户端代码:

//
// Imports
//
var Client = require('fabric-client');
var path = require('path');
var util = require('util');
var fs = require('fs');
const crypto = require('crypto');
const elliptic = require('elliptic');
const { KEYUTIL } = require('jsrsasign');
const config = require('./config');

//
// Script configuartion variables
//
var fcn = 'set';
var args = ["a","60"];
var priv = fs.readFileSync(config.PRIV, 'utf8');
var { prvKeyHex } = KEYUTIL.getKey(priv,'passphrase'); 
var cert = fs.readFileSync(config.CERT, 'utf8');
const EC = elliptic.ec;
const ecdsaCurve = elliptic.curves['p256'];
const ecdsa = new EC(ecdsaCurve);
const signKey = ecdsa.keyFromPrivate(prvKeyHex, 'hex');


//
// Config init
//
var client = Client.loadFromConfig('network_org1.yaml');
var targets = client.getPeersForOrg('org1');

// 
// Main
// 
client.initCredentialStores()
.then((nothing) => {

channel = client.getChannel(config.CHANNEL_NAME);

// 1. Generate unsigned transaction proposal
var transaction_proposal = {
  chaincodeId: config.CHAINCODE_NAME,
  channelId: config.CHANNEL_NAME,
  fcn: fcn,
  args: args,
};

var { proposal, tx_id } = channel.generateUnsignedProposal(transaction_proposal, 'org1', cert);

// 2. Hash the transaction proposal
var proposalBytes = proposal.toBuffer();
var digest = client.getCryptoSuite().hash(proposalBytes);
//const hash = crypto.createHash('sha256');
//hash.update(proposalBytes);
//var digest = hash.digest('hex');

// 3. Calculate the signature for this transacton proposal
console.log("digest: "+digest);   
console.log("signKey: ");
console.log(util.inspect(signKey));
var sig = ecdsa.sign(Buffer.from(digest, 'hex'), signKey);
var signature = Buffer.from(sig.toDER());
var signedProposal = {
  signature,
  proposal_bytes: proposalBytes,
};

// 4. Send the signed transaction proposal
var proposal_request = {
  signedProposal,
  targets
}
channel.sendSignedProposal(proposal_request)
.then((proposalResponses) => {
    console.log('Proposal responses:');
    console.log(util.inspect(proposalResponses));

    // TODO: Understand why the proposal signature is rejected by the peers

    // 5. Generate unsigned transaction
    var transaction_request = {
      proposalResponses,
      proposal,
    };
    return channel.generateUnsignedTransaction(transaction_request);
})  
.then((commitProposal) => {

    // 6. Sign the unsigned transaction
    var transactionBytes = commitProposal.toBuffer();
    var transaction_digest = client.getCryptoSuite().hash(transactionBytes);
    var transaction_sig = ecdsa.sign(Buffer.from(transaction_digest, 'hex'), signKey);        
    var transaction_signature = Buffer.from(transaction_sig.toDER());

    var signedTransaction = {
      signedProposal: transaction_signature,
      request: transaction_request
    }

    // 7. Commit the signed transaction
    return channel.sendSignedTransaction(signedTransaction);
})
.then((response) => {
    console.log('Successfully sent transaction');
    console.log('Return code: '+response.status);
});

});

任何可能已成功脱机签署交易的人的帮助都将是很棒的。

node.js hyperledger-fabric hyperledger hyperledger-fabric-sdk-js
1个回答
0
投票

回答我自己的问题。我的代码中有2个问题。

第一个与实际签名有关,需要在Fabric中以非常特定的方式完成。我必须创建此函数并将其应用于签名,以避免出现此问题:

function _preventMalleability(sig) {
const halfOrder = elliptic.curves.p256.n.shrn(1);
if (sig.s.cmp(halfOrder) === 1) {
    const bigNum = elliptic.curves.p256.n;
    sig.s = bigNum.sub(sig.s);
}
return sig;

第2d与各种提案/请求/交易结构的格式有关:

transaction_request = {
  proposalResponses: proposalResponses,
  proposal: proposal,
}

signedTransactionProposal = {
    signature: transaction_signature,
    proposal_bytes: transactionBytes,
}

signedTransaction = {
  signedProposal: signedTransactionProposal,
  request: transaction_request,
}

我创建了完整的(有效的)教程,并在此处提供了详细说明:https://gitlab.com/guillaume.goutaudier/wisekeydemo

© www.soinside.com 2019 - 2024. All rights reserved.