Hyperledger Fabric最佳实践-使用Chaincode加密状态数据库

扫码链接5000+新基建产业链上下游从业者,入群请备注“机智地+姓名+公司+岗位

由于区块链技术的快速的普及,IBM的Hyperledger Fabric项目飞速发展,不仅仅是因为它是区块链框架之一,具有一些非常独特的功能,例如许可的架构,即插即用组件,对机密事务的通道支持,模块化和可伸缩性。Hyperledger Fabric在这个区块链时代成为了革命性的事物,它具有巨大的潜力来改变行业。Hyperledger Fabric在过去几个月中取得了很大进步。无论您是Hyperledger Fabric的新手还是有一定经验,并且想要快速掌握Hyperledger Fabric的生产和开发所采用的最佳实践。我将在本系列中添加更多实践和技巧。我现在要发布我的首篇文章“使用Nodejs Chaincode加密和解密状态数据库。





重   点

在某些情况下,我们将处理敏感数据,例如将信用卡数据,银行信息,生物特征数据,健康信息等存储为分布式账本中业务应用程序的一部分。最终用户总是希望保护这些机密信息,即使数据库遭到破坏。在很多应用程序中,我们需要对数据库中的数据进行加密,这样即使有人进入数据库,他们也可能不知道数据是什么。然而,在区块链中,数据库被黑客攻击的可能性微乎其微。虽然黑客入侵区块链数据库的可能性较小,但在区块链数据库中存储用户数据时加密用户数据是一种很好的做法。随着近来Hyperledger Fabric的普及,让我们看一下如何使用Nodejs Chaincode加密进入数据库的数据。

在任何生产级应用程序上尝试此操作之前,您需要了解的一件事是,这会使操作变慢。此过程涉及两个额外的步骤-加密和解密数据。这会稍微降低您的应用程序的速度,并且取决于您拥有的数据库读取和写入的数量,这可能会对应用程序的性能产生重大影响。在决定加密数据库中的所有内容之前,请记住这一点。

业务流程

在开始加密之前,首先让我解释一下我在这里使用的链码逻辑。实际上,我们的链码在这里所做的就是简单的用户注册和登录。用户将通过提供用户名和密码在我们的应用程序上注册。这些凭据将以纯文本格式存储在数据库中,并且每当用户使用凭据登录时,所提供的凭据都将使用存储在数据库中的凭据进行验证。因此我们将在这些凭据中添加加密和解密层。简单 ??开始吧。

对于本例,我将保持这个简单操作介绍并同时为Nodejs使用一个内置的加密库。根据您正在处理的应用程序,您可以自定义加密实现并使其尽可能复杂。

注意:我将在本文中演示的这些加密和解密方法在Nodejs Runtime v10.0.0下工作。(Nodejs链代码的当前运行时环境。— Hyperledger Fabric 1.4.3)但是在将来的版本中,链代码的Nodejs运行时,将会移至v12.13.0,因此会有更好的方法可以加密和解密数据。但是技术将是相同的。为此我还在此示例存储库中添加了v12.13.0兼容的加密和解密方法。

更新:出于安全和隐私考虑,我们不应该通过交易明确传递机密信息(即密码),因为它涉及将这些密码存储在特定的交易标头中。如果网络中的其他用户可以扫描这些区块,则他们可以读取您的机密信息(即密码)。取而代之的是,您可以对密码进行哈希处理,然后通过交易传递(这是另一个故事)。我在这里描述的示例(注册和登录)是为了解释仅使用链码进行加密/解密的概念。

1、加密:

此示例项目的整个加密实用程序如下所示:

function encrypt(data){   


  const cipher = crypto.createCipher(‘aes256’, password);  


  let encrypted = cipher.update(data, ‘utf8’, ‘hex’);


  encrypted += cipher.final(‘hex’);   


  return encrypted;


}

encrypt()方法将完全可以按照您的想法执行。使用内置的基本加密器仅需五行代码。crypto()函数将通过环境变量(.env)使用预定义的加密密码获取参数数据,它将基于给定的算法aes256创建一个加密密钥,并使用该加密密钥对数据进行加密并返回加密的数据。这就是crypto()函数背后的全部思想。

#### 2、解密:

以下是此示例项目的解密实用程序:

function decrypt(cipherData)  {    


   const decipher = crypto.createDecipher(‘aes256’, password);    


   let decrypted = decipher.update(cipherData, ‘hex’, ‘utf8’);


   decrypted += decipher.final(‘utf8’);   


   return decrypted.toString();


}

decrypt()方法将解密加密的数据。crypto()函数将再次采用一个参数cipherData。使用密码,它将基于给定的算法aes256创建解密密钥,并使用解密密钥解密cipherData并返回纯数据。

3、链码的实现:

注意:术语password表示两个不同的参数。一个是业务应用程序的注册/登录密码,另一个是用于加密/解密数据的加密/解密密码(通过.env提供给环境)。

我们以前已经了解过了链码逻辑。所以当用户提交他的凭证(用户名和密码)时,我们应该在将它们放入数据库之前对它们进行加密。所以我们的第一个任务是将它们传递给encrypt()方法。一旦数据加密,encrypt()方法将返回加密数据。现在我们需要把这个加密的数据放在数据库中,密钥是username。困惑的?查看代码中的signUp()函数。

同样,当用户登录时,我们的链码需要验证用户名是否存在于数据库中,如果存在,它应该检查提交的密码是否正确。因此,为了检查密码是否正确,应该首先解密与特定密钥(用户名)相关联的数据,因为它是加密的。所以我们需要将这个加密的数据传递给decrypt()方法。一旦解密,如果提供的登录密码与与特定密钥(用户名)关联的密码匹配,它将验证用户登录。这是完整的代码。

‘use strict’;


const shim = require(‘fabric-shim’);


const util = require(‘util’);


const crypto = require(‘crypto’);


require(‘dotenv’).config()


const password = process.env.SECRET;

function encrypt(data){


   const cipher = crypto.createCipher(‘aes256’, password);


   let encrypted = cipher.update(data, ‘utf8’, ‘hex’);


   encrypted += cipher.final(‘hex’);


   return encrypted;


     }

  function decrypt(cipherData)  {


    const decipher = crypto.createDecipher(‘aes256’, password);


    let decrypted = decipher.update(cipherData, ‘hex’, ‘utf8’);


    decrypted += decipher.final(‘utf8’);


    return decrypted.toString();


        }

let Chaincode = class {

   async Init(stub) {


       console.info(‘=========== Instantiated Validation Chaincode===========’);


       return shim.success();


            }

async Invoke(stub) {


    let ret = stub.getFunctionAndParameters();


    console.info(ret);

    let method = this[ret.fcn];


    if (!method) {


      console.error(‘no function of name:’ + ret.fcn + ‘ found’);


      throw new Error(‘Received unknown function ‘ + ret.fcn + ‘ invocation’);


            }


    try {


      let payload = await method(stub, ret.params);


      return shim.success(payload);


         } 


    catch (err) {


      console.log(err);


      return shim.error(err);


            }


     }

async signUp(stub, args) {


      if (args.length != 2) {


     return Buffer.from(‘Incorrect number of arguments. Expecting 2’);


            }else{


   console.info(‘**Storing Credentials on Blockchain**’);

   const credentials  = {userName:args[0],password:args[1]};


   let data = JSON.stringify(credentials);


   let cipher = encrypt(data);

   await stub.putState(args[0], Buffer.from(JSON.stringify(cipher)));


   console.info(‘*Signup Successfull..Your Username is ‘+args[0]);


   return Buffer.from(‘Signup Successfull..Your Username is ‘+args[0]);


    }


}

async login(stub, args) {


  if (args.length != 2) {


     return Buffer.from(‘Incorrect number of arguments. Expecting 2’);


        }

  let userName=args[0];


  let password=args[1];


  let credentialsAsBytes = await stub.getState(args[0]); 

  if (!credentialsAsBytes || credentialsAsBytes.toString().length <= 0) {


    return Buffer.from(‘Incorrect Username..!’);


         }


  else{


  let data= JSON.parse(credentialsAsBytes);


  let decryptData= decrypt(data);


  let credentials= JSON.parse(decryptData);


  if (password!=credentials.password) {


  return Buffer.from(‘Incorrect Password..!’);


        }

  //Functions go here after signin


  console.log(‘Login Successfull..’);


  return Buffer.from(‘Login Successfull..’);


      }


  }

}

shim.start(new Chaincode());

 demo展示

git clone https://github.com/Salmandabbakuti/hlf-encryption.git


cd hlf-encryption 


chmod 777 node-start.sh && chmod 777 go-start.sh


./node-start.sh #nodejs chaincode encryption model (credentials storing and validation logic) head over to fauxton UI http://localhost:5984/_utils

./go-start.sh #golang chaincode encryption model (tuna supplychain logic)

Hyperledger Fabric最佳实践-使用Chaincode加密状态数据库

不加密的数据库中的纯数据。

Hyperledger Fabric最佳实践-使用Chaincode加密状态数据库

加密的数据库。
如您所见,加密和解密魔力正在发挥作用。

在下一篇文章中,我将通过三个简单的步骤来说明如何将Hyperledger Explorer连接到您的网络。

声明: 本文由入驻基智地平台的作者撰写,观点仅代表作者本人,不代表基智地立场;基智地发布此信息的目的在于传播更多信息,与本站立场无关。

发表评论

邮箱地址不会被公开。 必填项已用*标注