Skip to content

隐私保护

linj edited this page Nov 23, 2022 · 1 revision

隐私保护

数据的隐私保护是联盟链的关键技术之一,传统的隐私保护方案一般都是使用非对称加密算法对数据加密上链,获取数据时再解密。这些方案仅仅解决数据单方面的隐私保存,而无法做到隐私数据的动态分享。chain33联盟链使用代理重加密方案,结合存证合约,实现隐私数据的加密存储和动态分享。

代理重加密

算法简介

代理重加密(Proxy Re-Encryption, PRE)是一种密钥转换算法,可以将数据所有人owner公钥加密的密文转换为另一种密文,转换的密文可以由被授权人recipient的私钥进行解密。密文转换过程由一个半可信的代理服务器proxy执行,在执行该过程前,代理节点需要持有一个由授权人到被授权人的转换密钥,一般由授权人提前生成并发送给代理节点。通过转换密钥无法直接解析密文,最终还需要被授权人的私钥才能解密,所以代理节点没办法获取到明文信息。

功能组件

chain33代理重加密功能组件包括:

使用步骤

  • 数据所有人owner将隐私数据加密,通过存证合约保存在区块链上
  • 数据所有人owner对被授权人recipient生成重加密转换秘钥
  • 数据所有人owner将转换秘钥分发到代理重加密节点proxy
  • 被授权人recipient在区块链上查询隐私数据
  • 被授权人recipient向重加密节点proxy申请重加密
  • 被授权人recipient解密数据

使用方法

环境搭建

chain33联盟链

搭建方法参考联盟链开发环境搭建

代理重加密节点

软件包下载
wget https://bty33.oss-cn-shanghai.aliyuncs.com/chain33-Pre.tar.gz

tar xzvf chain33-Pre.tar.gz

cd chain33-Pre
配置

根据实际情况配置服务端口和节点私钥

# 对外重加密服务端口
bindAddr=":11801"

# 节点操作私钥
preServerKey="0x123456789abcdef0fedcba987654321"
启动
./chain33-pre -f chain33.pre.toml

sdk调用

数据所有人owner

// 生成账户
AccountInfo alice = new AccountInfo();
alice.setPrivateKey(OwnerPrivateKey);
alice.setPublicKey(TransactionUtil.getHexPubKeyFromPrivKey(OwnerPrivateKey));

// 生成对称秘钥
EncryptKey encryptKey = PreUtils.GenerateEncryptKey(HexUtil.fromHexString(alice.getPublicKey()));

// 生成重加密密钥分片
KeyFrag[] kFrags = new KeyFrag[numSplit];
try {
    kFrags = PreUtils.GenerateKeyFragments(HexUtil.fromHexString(alice.getPrivateKey()),
            HexUtil.fromHexString(RecipientPubKey), numSplit, threshold);
} catch (Exception e) {
    e.printStackTrace();
}

// 密钥分片发送到代理节点
String dhProof = PreUtils.ECDH(ServerPub, alice.getPrivateKey());
for(int i = 0; i < preClient.length; i++) {
    boolean result = preClient[i].sendKeyFragment(alice.getPublicKey(), RecipientPubKey, encryptKey.getPubProofR(),
            encryptKey.getPubProofU(), 100, dhProof, kFrags[i]);
    if (!result) {
        System.out.println("sendKeyFragment failed");
        return;
    }
}

// 数据加密
byte[] iv = AesUtil.generateIv();
byte[] cipher = AesUtil.encrypt(content, encryptKey.getShareKey(), iv);
System.out.println(cipher);

// 通过存证合约保存加密数据
byte[] contentHash;
try {
    contentHash = TransactionUtil.Sha256(content.getBytes("utf-8"));
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
    return;
}

String txEncode = StorageUtil.createEncryptNotaryStorage(cipher, contentHash, iv,
        "chain33-storage-key-pre-"+kFrags[0].getPrecurPub(), "", "storage", OwnerPrivateKey);
String submitTransaction = chain33Client.submitTransaction(txEncode);

数据被授权人recipient

// 生成账户
AccountInfo bob = new AccountInfo();
bob.setPrivateKey(RecipientPrivateKey);
bob.setPublicKey(TransactionUtil.getHexPubKeyFromPrivKey(RecipientPrivateKey));

// 申请重加密,需要两边的公钥
ReKeyFrag[] reKeyFrags = new ReKeyFrag[threshold];
for(int i = 0; i < threshold; i++) {
    reKeyFrags[i] = preClient[i].reencrypt(OwnerPubKey, bob.getPublicKey());
}

// 解密对称密钥,需要被授权人私钥
byte[] shareKeyBob;
try {
    shareKeyBob = PreUtils.AssembleReencryptFragment(HexUtil.fromHexString(bob.getPrivateKey()), reKeyFrags);
} catch (Exception e) {
    e.printStackTrace();
    return;
}

// 从链上获取密文
JSONObject resultJson = chain33Client.queryStorage("chain33-storage-key-pre-"+reKeyFrags[0].getPrecurPub());
JSONObject resultArray = resultJson.getJSONObject("encryptStorage");
String content = resultArray.getString("encryptContent");
byte[] fromHexString = HexUtil.fromHexString(content);

// 解密
String text = AesUtil.decrypt(fromHexString, HexUtil.toHexString(shareKeyBob));

详细示例,请参考PreOwnerPreRecipient

Clone this wiki locally