繁体   English   中英

Hyperledger Fabric Node.js SDK:离线交易签名问题

[英]Hyperledger Fabric Node.js SDK: Issue with offline transaction signatures

我正在尝试遵循本教程: 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);
});

});

任何可能在线下成功签署交易的人的任何帮助都会很棒。

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

第一个与需要在 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM