Hyperledger fabric Hyperledger结构上的身份管理

Hyperledger fabric Hyperledger结构上的身份管理,hyperledger-fabric,hyperledger,hyperledger-fabric-ca,hyperledger-fabric-sdk-js,Hyperledger Fabric,Hyperledger,Hyperledger Fabric Ca,Hyperledger Fabric Sdk Js,我正在使用Hyperledger fabric 1.4.1和最新版本的fabric contract api进行智能合约,使用fabric client进行低级api管理渠道创建和链码,使用fabric network与对等方进行交互。我已经参考了建立我的网络 我已经在nodejs中编写了一个基本的chaincode包,并建立了一个简单的1组织、1对等、1订购方网络。第一步是连接到对等节点,并使用fabric ca客户端创建管理员身份。根据示例,使用的注册id和密码是admin,adminpw。

我正在使用Hyperledger fabric 1.4.1和最新版本的fabric contract api进行智能合约,使用
fabric client
进行低级api管理渠道创建和链码,使用
fabric network
与对等方进行交互。我已经参考了建立我的网络

我已经在
nodejs
中编写了一个基本的chaincode包,并建立了一个简单的1组织、1对等、1订购方网络。第一步是连接到对等节点,并使用
fabric ca客户端
创建管理员身份。根据示例,使用的注册id和密码是
admin
adminpw
。这取决于环境

我用来创建和加入频道,然后安装和实例化链码的代码是

const CAClient = require('fabric-ca-client');
const client = require('fabric-client');
const User = client.User;
const fs = require('fs');
const path = require('path');
const basePath = path.resolve(__dirname, '../certs');
const readCryptoFile = filename => fs.readFileSync(path.resolve(basePath, filename)).toString();
const ccPath = path.resolve(__dirname, '../chaincode/src/ax-chaincode');
const url = require('url');
const http = require('http');

  let myClient = new client();
  const ordererConfig = {
    hostname: 'orderer0',
    url: 'grpc://localhost:7050',
    pem: readCryptoFile('ordererOrg.pem')
  };
  const orderer = myClient.newOrderer(ordererConfig.url, {
    pem: ordererConfig.pem,
    'ssl-target-name-override': ordererConfig.hostname
  });

  let peerConfig = {
    hostname: 'ax-peer',
    url: 'grpc://localhost:7051', // change to grpcs://ax-peer:7051 in some condition (no idea?)
    eventHubUrl: 'grpc://localhost:7053',
    pem: readCryptoFile('axOrg.pem')
  };
  const defaultPeer = myClient.newPeer(peerConfig.url, {
    pem: peerConfig.pem,
    'ssl-target-name-override': peerConfig.hostname
  });
  // console.log(defaultPeer);
  myClient.setStateStore(await client.newDefaultKeyValueStore({
    path: './ax-peer'
  }))

let url = 'http://localhost:7054'
    const ca = new CAClient(url, {
      verify: false
    });
    let enrollmentID = 'admin';
    let enrollmentSecret = 'adminpw';
    const enrollment = await ca.enroll({
      enrollmentID: 'admin',
      enrollmentSecret: 'adminpw'
    });
    user = new User(enrollmentID, myClient);
    // console.log(enrollment);
    await user.setEnrollment(enrollment.key, enrollment.certificate, 'AxOrgMSP');
上面将检查状态存储中是否有可用的
admin
user。关于上述过程的一些疑问

  • 此处生成的管理员用户可用于与同一组织的任何和所有对等方进行交互,假设只使用一个CA
  • 此标识的实际用途是什么,因为对于其余的函数,使用了由
    cryptogen
    为每个对等方生成的管理员标识(下面的代码)
  • 注册管理员时,
    ca.enroll()
    中不会传递任何
    attrs
    ,因此在查询身份
    角色时,字段自然返回null。共享的
    ca服务器
    链接清楚地为其分配了
    客户机、用户、对等机、验证器、审计员等角色。这不应该反映在这里,因为它使用
    admin
    adminpw
    注册id和secret
  • 继续代码

      // crypto material got from cryptogen and shifted to new folder
      let adminUser = await myClient.createUser({
        username: `Admin@ax-peer`,
        mspid: 'AxOrgMSP',
        cryptoContent: {
          privateKeyPEM: readCryptoFile('Admin@ax-org-key.pem'),
          signedCertPEM: readCryptoFile('Admin@ax-org-cert.pem')
        }
      });
      let txId = myClient.newTransactionID();
      let envelope_bytes = fs.readFileSync('./channel.tx');
      let channelConfig = myClient.extractChannelConfig(envelope_bytes);
      let signature = myClient.signChannelConfig(channelConfig);
      const request = {
          name: 'default',
          orderer: orderer,
          config: channelConfig,
          signatures: [signature],
          txId: txId
        };
       const response = await myClient.createChannel(request); // should be 200
       // rest of code joins channel, installs and instantiates chaincode
       // docker logs show init function being called in new cc container
    
    stateStore
    中有两个文件(如预期的那样),分别称为
    admin
    Admin@ax-对等
    。这些看起来像

    "name": "Admin@ax-peer",
      "mspid": "AxOrgMSP",
      "roles": null,
      "affiliation": "",
      "enrollmentSecret": "",
      enrollment: {
        "signingIdentity": "554a5f5cfc5a59231a04b7b051bcbcb4f79c4226ff336a4aa48b551de4a8428f",
        "certificate": "-----BEGIN CERTIFICATE----- xyz -----END CERTIFICATE-----"
      }
    
    从状态存储使用此用户时,等待myClient.getUserContext('admin',true),客户如何签署交易?我无法找到使用
    fabric客户端
    SDK创建的任何用户的私钥/证书

    现在,如果我使用
    fabric network
    API,就会实现一个
    FileSystemWallet()
    函数来存储每个用户的私有和公共证书

    const enrollment = await ca.enroll({ enrollmentID: `admin`, enrollmentSecret: `adminpw` });
    const identity = X509WalletMixin.createIdentity('AxOrgMSP', enrollment.certificate, enrollment.key.toBytes());
    wallet.import('admin', identity);
    
    此函数与ca.enroll()的作用相同,但以可见方式存储私人证书。如果我想使用
    fabric-client
    fabric-network
    SDK中创建的用户,我需要转换证书,我如何实现这一点

    TLDR-使用
    fabric client
    注册用户,然后使用
    fabric network
    中的
    Gateway()
    类提交与同一用户的交易


    任何建议、指导都将不胜感激。谢谢

    这个堆栈溢出中有太多问题,所以我只想对您发布的内容进行一些了解

  • 您从ca服务器注册的管理员标识称为admin,因为它是结构ca服务器的注册器,因此可以在ca服务器中注册更多标识。它不是其他任何东西(如结构网络)的管理员标识
  • 您已经使用了较低级别的api和结构网络机制来进行身份管理。在较低级别的api中,所有保存到文件系统的都是状态存储,公钥和私钥都存储在内存中,这纯粹是因为您调用所有内容的方式,而设置默认值恰好就是这种方式,不幸的是,使用低级api的其他方法可能需要显式地使用cryptoKeyStore设置cryptosuite。在wallet实现中,您可能使用了文件系统wallet,因此所有内容都被持久化到文件系统
  • 我的建议是,如果可以的话,从结构网络网关开始。然后,如果由于结构网络不能满足您的需要而需要切换到较低级别的api,那么您可以调用

    gateway.getClient()
    
    or
    
    network.getChannel()
    
    获取已使用网关配置和标识预先配置的客户端/通道。 要访问证书颁发机构,您可以使用
    gateway.getClient().getCertificateAuthority()

    所有这些都允许您使用wallet实现进行身份管理(wallet实现提供了不同的持久性机制,如内存、文件系统、couchdb或您自己编写的持久性机制)

    谢谢。我试试这个。尽管我在主目录(Ubuntu)中发现了一个名为
    .hfc key store
    的隐藏文件夹,该文件夹存储着与低级别API注册用户对应的私钥。我搜索了
    fabric客户端
    fabric ca客户端
    repo,发现
    hfc密钥存储
    是默认的存储位置。但这会变得有点混乱,因为公共证书和私钥存储在两个单独的文件夹中。是的,我有很多问题,刚刚完成了一个PoC,然后转向一个大规模的试点,所以我需要处理很多其他事情。我还注意到生成的密钥不断变化,与公共区块链实现不同,它不是基于注册ID和机密的确定性。每次注册,您创建一个新的私钥,并从该私钥生成一个新证书。因此,每次注册时,您都会得到一个不同的身份,而这个身份恰好具有相同的通用名称。另外请注意,如果使用非临时加密密钥库,则私钥仅存储在.hfc密钥库中。我确保将
    true
    置于持久性选项中。虽然有趣的是,网关中的所有标识函数都会传递给客户端实例,但当从网关注册用户时,会保存证书、pub和prvt密钥,而从客户端注册时只保存私钥和证书!