fabric 隐私保护之授权(一)

fabric 在隐私保护问题上提供不同层面的解决方案

1.粗粒度的通道隔离,通道是一个比较重的资源,动态性比较差,不适宜频繁使用

2.私有数据(private data collections)是fabric 1.3之后提供的一种隐私保护方案,但是使用不是那么灵活,修改涉及到合约的部署,应用场景不多。

3.比较常见的隐私保护方案是数据加密以及授权,接下来详细讲的内容

用场景说话

场景一:A需要将敏感数据上链,需要加密。同时,需要授权B查看,同一通道内的C和D无法查看数据内容。

解决方案:第一步,A的数据上链时,对明文数据使用对称加密(例如AES256),生成密文,将密文上链。

                 第二步,将上一步骤加密使用的密钥和随机向量 使用B的公钥做非对称加密(例如ECC),B的公钥获取可以从应用层获取。将加密后的密钥和向量发给B。(可以通过应用层发给B,也可以写到区块链上给B,具体看实现)

             第三步,B通过自己的私钥解密出加密数据的密钥和向量,使用这些密钥和向量对A的密文数据进行解密。

talk is cheap ,直接上代码。go 语言版智能合约

核心部分

func (t *Chaincode) submit(stub shim.ChaincodeStubInterface, args []string, encKey, IV, publicKey []byte) pb.Response {
   var err error
   key := args[0]
   value := args[1]
   ent, err := entities.NewAES256EncrypterEntity("ID", t.bccspInst, encKey, IV)
   if err != nil {
      return shim.Error(fmt.Sprintf("entities.NewAES256EncrypterEntity failed, err %s", err))
   }
//对称加密部分,使用了AES256加密算法
   err = encryptAndPutState(stub, ent, key, []byte(value)) //使用aesKey和Iv加密
   if err != nil {
      fmt.Println("encryptAndPutState err " + supplierKey)
      return shim.Error(err.Error())
   }
   aesenckey := &AESENCKEY{string(encKey), string(IV)}
   aesenckeyJSONasBytes, err := json.Marshal(aesenckey)
   endata, err := ECCEncryptWithPublickKey(randReader, aesenckeyJSONasBytes, string(publicKey))
   var authorizationKey string
   authorizationKey = "" //自定义授权键值
   err = stub.PutState(authorizationKey, endata)
   if err != nil {
      return shim.Error("PutState err:" + authorizationKey)
   }
   return shim.Success(nil)
}
//aes加密
func encryptAndPutState(stub shim.ChaincodeStubInterface, ent entities.Encrypter, key string, value []byte) error {
   ciphertext, err := ent.Encrypt(value)
   if err != nil {
      return err
   }
   return stub.PutState(key, ciphertext)
}
//aes加密解密​​​​
func getStateAndDecrypt(stub shim.ChaincodeStubInterface, ent entities.Encrypter, key string) ([]byte, error) {
   ciphertext, err := stub.GetState(key)
   if err != nil {
      return nil, err
   }
   if len(ciphertext) == 0 {
      return nil, errors.New("no ciphertext to decrypt")
   }
   return ent.Decrypt(ciphertext)
}
//ECC 加密 ,需要引入"github.com/ethereum/go-ethereum/crypto/ecies"包

func ECCEncryptWithPublickKey(rand string, data []byte, publickKey string) ([]byte, error) {
   var err error
   block, _ := pem.Decode([]byte(publickKey))
   if block == nil {
      fmt.Println("公钥解析错误:")
      return nil, err
   }
   // 解析公钥
   pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
   if err != nil {
      fmt.Println("ParsePKIXPublicKey公钥解析错误:")
   }
   pub := pubInterface.(*ecdsa.PublicKey)
   var pb = ecies.ImportECDSAPublic(pub)
   endata, err := ECCEncrypt(rand, []byte(data), *pb)
   if err != nil {
      panic(err)
   }
   fmt.Println("ecc公钥加密后:", hex.EncodeToString(endata))
   return endata, err
}
func ECCEncrypt(rand string, pt []byte, puk ecies.PublicKey) ([]byte, error) {
   r := strings.NewReader(rand)
   ct, err := ecies.Encrypt(r, &puk, pt, nil, nil)
   return ct, err
}
//ECC 解密部分
func ECCDecryptWithPrivateKey(data []byte, privateKey string) ([]byte, error) {
   var err error
   block, _ := pem.Decode([]byte(privateKey))
   if block == nil {
      fmt.Println("私钥解析错误:")
      return nil, err
   }
   // 解析私钥
   priInterface, err := x509.ParsePKCS8PrivateKey(block.Bytes)
   pri := priInterface.(*ecdsa.PrivateKey)
   if err != nil {
   }
   var pi = ecies.ImportECDSA(pri)
   dedata, err := ECCDecrypt(data, *pi)
   if err != nil {
      panic(err)
   }
   fmt.Println("私钥解密:", string(dedata))
   return dedata, err
}

完整代码有空的时候会放到github上

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值