简介
在 Fabric 区块链网络中,用户可以把业务数据按照特定的业务逻辑上链。对于链上的数据,多个参与方之间均透明可见证。对于不能对链上其他组织直接开放的隐私数据,用户可以直接把相关数据的 hash 值存储在链上作为见证。但是存在如下情形,用户数据不能直接向其他组织直接开放,但其他组织又需要根据链上这些数据进行特定的运算背书。
针对以上场景,TBaaS 引入同态加密的能力,很好的保证了数据隐私性,链上透明性,以及数据可操作性。
TBaaS 的同态加密能力特点
TBaaS 的同态加密能力,主要体现在以下两个方面:
TBaaS 提供了一个单独的用户工具 paitool, 用户可以使用这个工具做一些基本的同态公私钥生成,同态加密和同态解密操作。
TBaaS 在 Go 语言智能合约中,额外引入了 paillier 包,增加了同态算法的 API 接口。用户可以通过 API 接口,实现同态公私钥生成、同态加密、同态解密、同态加法、同态减法以及部分同态乘法(密文和明文相乘)。
下面将分别对 paitool 和 Go 智能合约的 paillier 包进行说明。
同态加密算法工具 paitool
使用说明
命令 | 描述 | 参数 |
genkey | 生成 Paillier 算法的公私钥对 | length:公钥长度,即安全等级,[]代表可选,默认为2048 pkout:新公钥的文件路径 skout:新私钥的文件路径 |
encrypt | 加密 | pkin:用于加密的公钥的文件路径,可以是 genkey 生成的公钥文件路径 plaintext:要加密的明文数字,十进制形式的数字。假设公钥值为 N,长度为 n bit,该数字范围只能取 (-N/2,N/2],即明文的安全长度为 n - 2 bit(不算符号的长度) cipherout:生成的密文的指定文件路径 |
decrypt | 解密 | skin:解密使用的私钥的文件路径 cipherin:需要解密的密文文件路径 |
示例
genkeyn执行以下命令,生成的新公钥存在 pk.pai 文件中,新私钥存在 sk.pai 文件中。n公钥是一行16进制字符串,私钥是两行16进制字符串。示例中的公钥是 2048-bit 长的二进制串,16进制编码后为512位字符串。私钥是两段 1024-bit 长的二进制串,16进制编码后为两段256位字符串。
./paitool genkey [-length=2048] -pkout=pk.pai -skout=sk.pai
encryptn执行以下命令,工具会使用 pk.pai 中存储的公钥对数字10进行加密,生成的密文存在文件 cipher.pai 中。n密文是一个16进制字符串,可以直接作为 paitool 工具的解密功能入参,或者在调用 Paillier chaincode 的解密、同态运算接口时作为密文入参。
./paitool encrypt -pkin=pk.pai -plaintext=10 -cipherout=cipher.pai
decryptn执行以下命令,工具会解析文件 sk.pai 中的私钥,对文件 cipher.pai 中的密文进行解密,解密后的明文结果会直接输出。
./paitool decrypt -skin=sk.pai -cipherin=cipher.pai
Go 语言智能合约 paillier 包接口说明
Go 语言智能合约 paillier 包是根据轻量同态加密 Paillier 算法实现的,该算法是由 Paillier Pascal 于1999年提出。用户在 TBaaS 中使用 Go 语言智能合约时,可直接 import paillier 包,使用相关的接口。该算法支持加法、减法、部分乘法,但对运算的输入和输出有范围限制,即参与运算的数和运算结果的长度都不能比公钥长,否则会溢出。
paillier 包支持接口
接口 | 功能 | 参数 | 输出 |
GenerateKey(rand io.Reader, length int) (*PrivateKey, error) | 生成私钥 | rand:io.Reader,是随机数生成器,推荐使用 crypto/rand 库中的 rand.Reader length:int,是公钥长度,也代表安全性,推荐使用大于2048的整数 | 私钥:用于解密,可导出成员 PublicKey 作为公钥进行加密 错误信息 |
Encrypt(pk *PublicKey, plaintext string) (string, error) | 加密,生成密文 | pk:公钥 plaintext:string 类型明文,格式需要是以 string 表示的整数,可以是负数 | 密文:string 类型 错误信息 |
Decrypt(sk *PrivateKey, ciphertext string) (string, error) | 解密,用私钥 sk 从密文中获取明文 | sk:私钥 ciphertext:string 类型密文 | 明文:string 类型表示的数字 错误信息 |
Neg(pk *PublicKey, ciphertext string) (string, error) | 计算密文中被加密数字的相反数,生成其相反数的密文 | pk:公钥 ciphertext:string 类型密文 | 密文:string 类型,其内容为原信息的相反数 错误信息 |
AddCipher(pk *PublicKey, cipher1 string, cipher2 string) (string, error) | 计算 cipher1 和 cipher2 中明文的和,并生成和的新密文 | pk:公钥 cipher1,cipher2:string 类型的密文 | 密文:string 类型 错误信息 |
Add(pk *PublicKey, cipher string, plain string) (string, error) | 计算密文 cipher 中被加密的数与明文数字 plain 的和,并生成和的新密文 | pk:公钥 cipher:string 类型密文 plain:string 类型明文,以 tring 表示的一个数,可以为负数 | 密文:string 类型 错误信息 |
SubCipher(pk *PublicKey, cipher1 string, cipher2 string) (string, error) | 计算 cipher1 和 cipher2 中明文的差(cipher1 - cipher2),并生成差的新密文 | pk:公钥 cipher1,cipher2:string 类型的密文 | 密文:string 类型 错误信息 |
Sub(pk *PublicKey, cipher string, plain string) (string, error) | 计算密文 cipher 中被加密的数与明文数字 plain 的差(cipher - plain),并生成差的新密文 | pk:公钥 cipher:string 类型密文 plain:string 类型明文,以 string 表示的一个数,可以为负数 | 密文:string 类型 错误信息 |
Mul(pk *PublicKey, cipher string, plain string) (string, error) | 计算密文 cipher 中被加密的数与明文数字 plain 的乘积,并生成积的新密文 | pk:公钥 cipher:string 类型密文 plain:string 类型明文,以 string 表示的一个数,可以为负数 | 密文:string 类型 错误信息 |
GetPublicKeyHex(pk *PublicKey) string | 生成公钥的16进制字符串表达方式 | pk:公钥 | string 类型的公钥字符串 |
GetPublicKeyFromHex(hex string) (*PublicKey, error) | 从16进制字符串中恢复出公钥 | string:16进制字符串 | 公钥 |
WritePublicKeyToFile(pk *PublicKey, file string) error | 将公钥写入文件 | pk:公钥 file:文件名 | 错误信息 |
ReadPublicKeyFromFile(file string) (*PublicKey, error) | 从文件中读取公钥 | file:文件名 | 公钥 错误信息 |
GetPrivateKeyHex(sk *PrivateKey) string | 生成私钥的16进制字符串表达方式 | sk:私钥 | string 类型的私钥字符串 |
GetPrivateKeyFromHex(hex string) (*PrivateKey, error) | 从16进制字符串中恢复出私钥 | string:16进制字符串 | 私钥 |
WritePrivateKeyToFile(sk *PrivateKey, file string) error | 将私钥写入文件 | sk:私钥 file:文件名 | 错误信息 |
ReadPrivateKeyFromFile(file string) (*PrivateKey, error) | 从文件中读取私钥 | file:文件名 | 私钥 错误信息 |
GetCiphertextHex(cipher string) string | 生成密文的16进制字符串表达方式 | cipher:密文 | string 类型的密文字符串 |
GetCiphertextFromHex(hex string) string | 从16进制字符串中恢复出密文 | string:16进制字符串 | 密文 |
WriteCiphertextToFile(cipher string, file string) error | 将密文写入文件 | cipher:密文 file:文件名 | 错误信息 |
ReadCiphertextFromFile(file string) (string, error) | 从文件中读取密文 | file:文件名 | 密文 错误信息 |