乐趣区

关于密码学:铜锁-Bulletproofs-Range-使用教程

文|王祖熙(花名:金九 )

蚂蚁团体开发工程师
负责国产化明码库 Tongsuo 的开发和保护专一于密码学、高性能网络、网络安全等畛域

本文 5316 字 浏览 12 分钟

背景

在许多利用场景中,当须要证实一个值满足特定的范畴条件、又不心愿走漏该值的具体大小时,传统的证实办法可能须要裸露更多的信息。而范畴证实能够提供一种更高效、更隐衷爱护的形式来实现这一指标。

Bulletproofs Range Proof (范畴证实) 就是这样一种高效的范畴证实技术,Range Proof 也是 Bulletproofs 算法的一个重要利用,用于证实一个值位于指定的范畴内:[0,2n-1] (n 为指数,是 Range Proof 的重要参数)

在加密货币交易中,范畴证实能够用于证实交易金额在特定范畴内,以确保交易的合法性和爱护用户隐衷,这能够避免歹意用户创立有效的交易或泄露敏感的交易金额信息。而 Bulletproofs 具备 Proof 较小的特点,能够大大减小交易成本。以下是一些应用 Bulletproofs 的区块链我的项目:

  • Monero:Monero (门罗币) 是一种基于隐衷的加密货币,它应用了 Bulletproofs 技术来实现交易的隐衷和匿名性。Bulletproofs 能够帮忙减小 Monero 交易的大小,进步交易的效率,并爱护用户的隐衷。
  • Grin:Grin 是一种基于 MimbleWimble 协定的加密货币,它应用了 Bulletproofs 技术来实现交易的隐衷和可扩展性。Bulletproofs 在 Grin 中被用于构建零常识证实,以验证交易的有效性和爱护用户的隐衷。
  • Zcoin:Zcoin 是一种基于零常识证实的隐衷加密货币,它应用了 Bulletproofs 技术来改良其零常识证实计划。Bulletproofs 能够帮忙 Zcoin 实现更高效和更紧凑的证实,进步隐衷爱护的性能。

Bulletproofs 的零常识证实和范畴证实个性使其成为进步区块链隐衷和性能的无力工具,因而在隐衷爱护和可扩展性方面具备宽泛的利用后劲。

命令行

公共参数 (-ppgen/-pp)

生成公共参数

$ tongsuo bulletproofs -ppgen -out ./pp.pem -curve_name sm2 -gens_capacity 16 -party_capacity 4

参数阐明:

  • 其中 bulletproofs 是 tongsuo 的子命令:bulletproofs 性能,不再赘述
  • -ppgen:是 bulletproofs 的子命令,指公共参数的生成,pp 是 pub_param 的缩写,gen 是 generate 的缩写
  • -out:输入文件门路
  • -curve_name:椭圆曲线名称
  • -gens_capacity:椭圆曲线点生成器的容量,对于 Range Proof 来说,该数是 Range 的比特位数。这里是 16 位,也就是证实的范畴为:[0,216-1],即 [0,65535]
  • -party_capacity:能够生成聚合证实的最大参与方数量,仅对 Range Proof 无效,也就是批量范畴证实的最大个数。这里是 4,也就是最多只能批量证实或验证 4 个数

文本显示公共参数

-pp 是用来显示公共参数的子命令。

$ tongsuo bulletproofs -pp -in ./pp.pem -text -noout
Bulletproofs Public Parameter:
curve: SM2 (1172)
gens_capacity: 16
party_capacity: 4
G[n]:
    [0]: 02:b2:83:7e:13:99:e9:d7:93:57:8d:11:4a:e7:f1:01:66:0b:b2:7b:d9:2e:a4:c7:8a:bf:a6:10:89:0c:c6:93:e9
    [1]: 02:7e:44:85:96:15:53:db:f2:72:66:c5:af:b6:4d:d2:1b:f0:b7:aa:3a:f2:3a:14:fd:99:2c:e0:5d:56:26:2e:fb
    [2]: 02:81:57:f9:d5:38:f2:11:16:f4:a1:45:60:8e:50:da:31:2d:6a:c8:fa:19:d3:36:90:66:01:14:2c:14:53:0b:f0
    [3]: 03:20:46:61:ea:ff:68:49:a3:e3:d9:d5:3b:6a:a0:22:c4:78:47:c1:d0:1b:08:d7:42:8b:c9:19:d1:a8:f5:e5:18
    # 太长了,两头省略了 #
    [60]: 03:a7:b9:80:6f:ff:7d:30:6e:86:9d:d4:e0:cd:52:ee:cc:10:7e:0d:0e:6e:26:25:ae:bb:5d:48:b3:43:c0:4a:a0
    [61]: 03:4a:b8:07:7f:44:49:b2:0e:b9:26:4e:56:97:76:89:57:22:e7:34:3d:c2:e1:d9:57:a3:73:0d:dd:49:79:19:f0
    [62]: 03:9f:24:5c:30:a8:6d:08:75:8a:4c:79:04:f0:e5:41:b7:3d:41:84:71:51:77:8e:41:36:4a:9b:b6:24:bb:26:73
    [63]: 03:97:c7:a6:45:70:19:a2:ae:ff:52:fa:1c:c7:f2:e6:a0:dd:91:fd:e8:97:d8:c2:9b:4e:41:a4:9c:17:73:63:8b
H[n]:
    [0]: 03:0a:b0:b0:4c:09:7f:ec:e2:a8:41:c0:fc:75:ad:f3:02:cf:af:6a:77:a7:96:35:d8:ce:8b:6a:4b:02:a3:8c:49
    [1]: 02:5e:1d:90:be:23:90:a9:a6:02:b2:9f:b2:07:70:eb:f5:d3:0d:93:65:bd:ac:60:21:50:cc:d2:05:29:29:9d:5d
    [2]: 03:3c:d3:ef:45:77:e1:0d:e4:51:6e:73:ae:61:04:fc:6a:8d:f1:69:a6:9e:ca:d8:c4:bb:63:4c:37:c6:30:c9:05
    [3]: 03:b1:1d:fb:e0:f3:1f:33:a1:12:cf:58:0b:2c:a4:13:68:7f:42:57:98:f4:3d:0f:0c:88:98:f7:31:0e:e7:35:27
    # 太长了,两头省略了 #
    [60]: 02:bc:b6:19:81:7e:53:21:f0:b9:00:fe:b2:77:47:4c:e5:d8:f4:57:43:d0:5a:52:ba:78:59:6c:e6:00:78:23:04
    [61]: 03:cd:c2:e8:fc:27:0b:2c:af:6b:39:d7:c0:7b:2a:58:61:dd:36:8e:72:3d:6c:c1:1f:b0:12:3e:9d:78:c3:7b:cd
    [62]: 03:27:53:ec:07:b8:05:fe:24:5f:77:1d:62:c1:32:8f:75:8b:1e:bc:4f:92:ca:02:c1:ef:26:73:b3:c7:41:83:32
    [63]: 02:f0:7c:60:03:68:41:08:27:6b:d8:0b:f1:37:ba:0f:68:ac:33:f9:2b:4d:b6:74:d7:21:9f:7b:73:4c:8c:2e:90
U: 03:34:aa:13:0f:76:92:8d:33:1f:62:00:70:ff:04:86:08:9c:c7:3b:77:66:af:77:59:ce:d9:69:66:86:60:db:24
H: 02:e5:21:75:20:47:fb:c2:76:c2:86:3c:10:e0:4c:1e:72:66:26:7b:3d:5d:ac:5b:a0:de:ab:11:d3:56:bd:fc:f1

如上后果所示,G[n] 和 H[n] 就是随机生成椭圆曲线 SM2 上的点,n=gens_capacity*party_capacity,上图是 64,两头一些随机点因为太长太占篇幅省略掉了。

证据 (-witness)

生成证据

$ tongsuo bulletproofs -witness -pp_in ./pp.pem -out witness_range.pem 11 22 10000

$ tongsuo bulletproofs -witness -pp_in ./pp.pem -out witness_range_capacity_exceeded.pem 11 22 33 44 55

$ tongsuo bulletproofs -witness -pp_in ./pp.pem -out witness_range_exceeded.pem 65536

$ tongsuo bulletproofs -witness -pp_in ./pp.pem -out witness_range_exceeded_one.pem 11 22 65536

参数阐明:

  • -witness:是用来生成 / 显示证据的子命令
  • -pp_in:指定公共参数文件所在门路
  • -out:生成的证据文件门路,上述四条命令生成的四个证据文件别离为:

    1. witness_range.pem:失常的 Range 证据文件

    2. witness_range_capacity_exceeded.pem:容量超出的证据文件,因为生成的公共参数反对的批量证实和验证个数为最多 4 个,这里指定了 5 个

    3. witness_range_exceeded.pem:Range 范畴超出的证据文件,因为生成的公共参数可证实和验证的二进制比特位为 16,验证范畴是 [0,216),也就是 0-65535,提交的 65536 在验证时会失败

    4. witness_range_exceeded_one.pem:指定了 3 个数 (11、22 和 65536),其中 11 和 22 失常,但 65536 超出范围了,这个 witness 文件生成的 Proof 在验证时也会失败

显示证据

$ tongsuo bulletproofs -witness -in witness_range.pem -text
Witness:
curve: SM2 (1172)
H: 02:e5:21:75:20:47:fb:c2:76:c2:86:3c:10:e0:4c:1e:72:66:26:7b:3d:5d:ac:5b:a0:de:ab:11:d3:56:bd:fc:f1
V[n]:
    [0]: 03:a0:80:74:69:3a:9e:ad:d3:c2:f2:8f:90:db:34:11:89:b5:ab:2a:da:e5:e5:45:1c:0a:e3:63:86:f2:0e:92:13
    [1]: 02:1b:1d:6a:c4:e5:ae:80:19:0c:0d:ce:48:bf:7e:19:c1:b3:a2:9a:ce:da:d1:40:dc:bd:de:43:b4:e3:c8:6a:14
    [2]: 02:b3:76:ca:f5:0a:fc:37:9d:dd:55:52:37:f7:2c:4e:a4:9c:91:41:f4:d0:ea:2e:64:05:2e:dd:f7:fb:0a:1b:1d
v[n]:
    [0]: 11 (0xb)
    [1]: 22 (0x16)
    [2]: 10000 (0x2710)
r[n]:
    [0]: 4d:df:5b:b7:fb:ed:73:1a:cc:40:53:19:4f:35:e8:f5:bf:f8:08:30:cc:6d:f7:25:77:87:f1:a4:87:1e:d8:ea
    [1]: 57:cb:b6:2a:db:b5:5c:e9:33:27:73:88:72:b4:18:18:1e:da:41:b1:71:32:8f:29:f4:e7:cc:c7:a4:f3:3b:31
    [2]: 00:88:b0:2c:3f:a0:4d:8a:91:1e:fa:3c:9b:0a:c2:e0:b1:89:7a:b4:b2:2c:e6:50:75:f7:61:60:d3:2c:b9:33:94
-----BEGIN BULLETPROOFS WITNESS-----
AAAElALlIXUgR/vCdsKGPBDgTB5yZiZ7PV2sW6DeqxHTVr388QAAAAMDoIB0aTqe
rdPC8o+Q2zQRibWrKtrl5UUcCuNjhvIOkhMAAhsdasTlroAZDA3OSL9+GcGzoprO
2tFA3L3eQ7TjyGoUAAKzdsr1Cvw3nd1VUjf3LE6knJFB9NDqLmQFLt33+wobHQAA
AAADK03fW7f77XMazEBTGU816PW/+AgwzG33JXeH8aSHHtjqK1fLtirbtVzpMydz
iHK0GBge2kGxcTKPKfTnzMek8zsxK4iwLD+gTYqRHvo8mwrC4LGJerSyLOZQdfdh
YNMsuTOUAAAAAysAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACysAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFisAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAnEA==
-----END BULLETPROOFS WITNESS-----

如上后果所示,witness 中蕴含了椭圆曲线名称,H 点 (与公共参数统一),密文证据 V,明文证据 v 和随机数 r。

证实 (-prove/-proof)

生成 Range 证实 (-prove)

$ tongsuo ./apps/openssl bulletproofs -prove -pp_in ./pp.pem -witness_in witness_range.pem -out proof-range.pem

$ tongsuo bulletproofs -prove -pp_in ./pp.pem -witness_in witness_range_exceeded.pem -out proof-range-exceeded.pem

$ tongsuo bulletproofs -prove -pp_in ./pp.pem -witness_in witness_range_exceeded_one.pem -out proof-range-exceeded-one.pem

$ tongsuo ./apps/openssl bulletproofs -prove -pp_in ./pp.pem -witness_in witness_range_capacity_exceeded.pem -out proof-range-capacity-exceeded.pem
May be extra arguments error, please use -help for usage summary.
80C54E0201000000:error:1F800068:lib(63):BP_RANGE_PROOF_prove:reason(104):crypto/zkp/bulletproofs/range_proof.c:276:

参数阐明:

  • -pp_in:指定公共参数文件所在门路
  • -witness_in:指定证据文件所在门路
  • -out:指定证实的输入门路,输入的文件蕴含两段:R1CS PROOF 和 WITNESS,别离为 Proof 和 Witness

由证据文件 witness_range.pemproof-range-exceeded.pemproof-range-exceeded_one.pem 和 proof-range-capacity-exceeded.pem 别离生成相应的证实 (Proof),能够看出,超出批量容量个数的证据生成证实时报错了。

显示证实 (-proof)

$ tongsuo bulletproofs -proof -in proof-range.pem -text
Range Proof:
A: 03:03:29:b3:64:40:02:99:1a:4d:22:4d:af:4e:6c:8d:14:84:e7:6a:94:05:bd:91:57:d0:40:7a:c1:fe:e5:96:94
S: 03:12:46:e0:97:01:a2:d6:bf:ea:90:5c:01:2c:0c:fe:ae:5f:8a:da:38:ce:0e:6c:29:a4:08:46:fb:34:ed:5b:ed
T1: 02:c3:0b:2d:49:8f:b1:e5:bb:2a:d6:40:51:8a:2c:6a:58:d8:59:0c:87:f1:e4:b4:81:f5:b1:a3:2d:d6:90:7e:60
T2: 02:eb:34:90:10:ed:b1:32:99:9f:1f:ff:09:7a:d3:15:4c:be:34:69:59:48:a4:fd:4b:e5:70:2a:d1:7a:30:9b:82
taux: 38:e7:c2:84:3c:16:c3:8e:7d:5e:8d:38:d5:8b:8e:4a:8e:45:95:db:e3:49:87:7f:36:63:b8:fb:6a:e8:0b:c4
mu: 00:b8:29:e5:f8:75:a3:32:f6:38:23:40:2e:90:ec:35:b0:84:2a:00:1d:04:6b:2e:67:53:50:ec:c0:98:ff:79:6b
tx: 00:8f:46:12:73:9d:e6:cb:aa:3e:21:4b:4d:f8:b4:66:91:40:fd:7e:bb:c0:b5:f7:07:ce:a5:f2:ff:98:86:62:40
inner proof:
    n: 6
    L[n]:
        [0]: 02:e7:34:ca:e7:98:a6:52:a6:83:ce:62:a6:c0:50:ec:86:4b:98:e9:19:c7:54:07:3d:d5:e3:f5:8d:fb:50:e0:c5
        [1]: 03:53:38:d4:99:6d:7d:cd:88:88:e5:92:b2:ce:13:f4:ce:3b:fe:e2:5f:12:c5:4b:d0:93:83:b6:35:fd:0d:03:24
        [2]: 03:a6:f9:93:14:b2:46:02:34:96:08:39:d2:28:65:83:1e:27:20:96:b1:e5:e7:f8:1f:a6:7a:9e:e7:df:60:e2:79
        [3]: 02:f4:b5:c4:76:a5:5e:c0:69:c5:a2:4d:24:52:9a:90:87:e3:cc:2a:3d:52:0b:3e:58:24:2e:c7:66:4e:65:b3:cf
        [4]: 03:44:5b:eb:8f:1c:91:a1:7f:9e:a7:9b:ed:fb:52:81:90:3a:4a:dc:1d:ee:dd:6b:66:71:c2:14:3c:7a:d4:c3:03
        [5]: 03:b7:53:59:4d:69:cf:12:85:41:52:60:f9:d2:c2:a1:82:88:6e:af:f3:33:f6:36:55:eb:99:61:ac:37:7d:c4:74
    R[n]:
        [0]: 03:08:3d:7c:3c:21:7f:7f:79:bb:43:05:ec:0b:76:41:9f:54:13:d0:c9:2d:7a:23:67:91:92:7f:74:ce:3e:ef:04
        [1]: 02:a7:f1:f2:de:ad:89:7c:1a:17:06:df:59:81:9f:9e:93:51:22:19:a7:74:9a:30:6c:ca:e8:6b:c5:8b:c2:6f:85
        [2]: 02:fc:0a:45:3b:86:37:a0:fd:6a:8f:92:0a:30:b9:2d:99:c5:2c:89:20:40:23:39:58:b0:da:f4:de:0c:5c:2a:ad
        [3]: 02:da:69:0e:87:f5:57:8d:a1:44:c7:9a:40:d2:d3:f5:aa:c1:e1:08:5c:fd:d4:37:9a:75:8a:9b:4e:2f:fe:56:79
        [4]: 02:35:7c:29:a0:47:17:84:71:ed:9c:bd:ed:9e:fc:9f:83:81:33:9d:c0:30:15:54:6f:53:f0:49:79:6d:a4:60:51
        [5]: 03:a0:88:ec:8a:de:4a:59:78:a7:f4:c9:5d:9a:a0:b9:ab:58:93:61:22:ef:ec:66:5c:1e:53:f1:a3:d6:bb:eb:b3
    a: 00:bb:f6:3c:a4:5c:d8:8e:7c:a6:fc:e1:c6:68:83:b3:67:49:b0:1e:a4:0d:1c:43:8d:a9:21:49:f2:cc:97:70:6e
    b: 00:98:f8:f1:9e:fd:5c:3d:39:2f:cf:4b:f4:78:2d:3d:26:1b:ca:cc:35:25:17:d6:ca:78:65:34:f4:65:81:fa:5b
-----BEGIN BULLETPROOFS RANGE PROOF-----
AAAElAAAAAQDAymzZEACmRpNIk2vTmyNFITnapQFvZFX0EB6wf7llpQDEkbglwGi
1r/qkFwBLAz+rl+K2jjODmwppAhG+zTtW+0CwwstSY+x5bsq1kBRiixqWNhZDIfx
5LSB9bGjLdaQfmAC6zSQEO2xMpmfH/8JetMVTL40aVlIpP1L5XAq0Xowm4IAAAAD
KzjnwoQ8FsOOfV6NONWLjkqORZXb40mHfzZjuPtq6AvEK7gp5fh1ozL2OCNALpDs
NbCEKgAdBGsuZ1NQ7MCY/3lrK49GEnOd5suqPiFLTfi0ZpFA/X67wLX3B86l8v+Y
hmJAAAAAAiu79jykXNiOfKb84cZog7NnSbAepA0cQ42pIUnyzJdwbiuY+PGe/Vw9
OS/PS/R4LT0mG8rMNSUX1sp4ZTT0ZYH6WwAAAAYC5zTK55imUqaDzmKmwFDshkuY
6RnHVAc91eP1jftQ4MUDUzjUmW19zYiI5ZKyzhP0zjv+4l8SxUvQk4O2Nf0NAyQD
pvmTFLJGAjSWCDnSKGWDHicglrHl5/gfpnqe599g4nkC9LXEdqVewGnFok0kUpqQ
h+PMKj1SCz5YJC7HZk5ls88DRFvrjxyRoX+ep5vt+1KBkDpK3B3u3WtmccIUPHrU
wwMDt1NZTWnPEoVBUmD50sKhgohur/Mz9jZV65lhrDd9xHQAAAAGAwg9fDwhf395
u0MF7At2QZ9UE9DJLXojZ5GSf3TOPu8EAqfx8t6tiXwaFwbfWYGfnpNRIhmndJow
bMroa8WLwm+FAvwKRTuGN6D9ao+SCjC5LZnFLIkgQCM5WLDa9N4MXCqtAtppDof1
V42hRMeaQNLT9arB4Qhc/dQ3mnWKm04v/lZ5AjV8KaBHF4Rx7Zy97Z78n4OBM53A
MBVUb1PwSXltpGBRA6CI7IreSll4p/TJXZqguatYk2Ei7+xmXB5T8aPWu+uz
-----END BULLETPROOFS RANGE PROOF-----
Witness:
curve: SM2 (1172)
H: 02:e5:21:75:20:47:fb:c2:76:c2:86:3c:10:e0:4c:1e:72:66:26:7b:3d:5d:ac:5b:a0:de:ab:11:d3:56:bd:fc:f1
V[n]:
    [0]: 03:a0:80:74:69:3a:9e:ad:d3:c2:f2:8f:90:db:34:11:89:b5:ab:2a:da:e5:e5:45:1c:0a:e3:63:86:f2:0e:92:13
    [1]: 02:1b:1d:6a:c4:e5:ae:80:19:0c:0d:ce:48:bf:7e:19:c1:b3:a2:9a:ce:da:d1:40:dc:bd:de:43:b4:e3:c8:6a:14
    [2]: 02:b3:76:ca:f5:0a:fc:37:9d:dd:55:52:37:f7:2c:4e:a4:9c:91:41:f4:d0:ea:2e:64:05:2e:dd:f7:fb:0a:1b:1d
    [3]: 02:0d:30:77:fb:4f:a5:f6:7d:e4:78:f3:84:ca:96:28:c2:46:92:df:2b:dc:57:f7:f8:8b:8a:33:63:c9:6d:91:7b
-----BEGIN BULLETPROOFS WITNESS-----
AAAElALlIXUgR/vCdsKGPBDgTB5yZiZ7PV2sW6DeqxHTVr388QAAAAQDoIB0aTqe
rdPC8o+Q2zQRibWrKtrl5UUcCuNjhvIOkhMAAhsdasTlroAZDA3OSL9+GcGzoprO
2tFA3L3eQ7TjyGoUAAKzdsr1Cvw3nd1VUjf3LE6knJFB9NDqLmQFLt33+wobHQAC
DTB3+0+l9n3kePOEypYowkaS3yvcV/f4i4ozY8ltkXsA
-----END BULLETPROOFS WITNESS-----

能够看出 proof-range.pem 中蕴含了两段:RANGE PROOF 和 WITNESS,这里 WITNESS 的 V 就是密文证据。

验证 (-verify)

$ tongsuo bulletproofs -verify -pp_in ./pp.pem -in proof-range.pem
The proof is valid

$ tongsuo bulletproofs -verify -pp_in ./pp.pem -in proof-range-exceeded.pem
The proof is invalid

$ tongsuo bulletproofs -verify -pp_in ./pp.pem -in proof-range-exceeded-one.pem
The proof is invalid

如上后果,能够看出,在范畴内的 Proof 验证后果无效,超出范围的验证有效。

Demo

代码

#include <stdio.h>
#include <stdlib.h>
#include <openssl/bulletproofs.h>

static int range_proofs_test(int bits, int64_t secrets[], int len)
{
    int ret = 0, i;
    BIGNUM *v = NULL;
    BP_TRANSCRIPT *transcript = NULL;
    BP_PUB_PARAM *pp = NULL;
    BP_WITNESS *witness = NULL;
    BP_RANGE_CTX *ctx = NULL;
    BP_RANGE_PROOF *proof = NULL;

    v = BN_new();
    
    /* 创立交互抄本对象,证实者和验证者须要应用雷同的办法和标签,否则验证失败 */
    transcript = BP_TRANSCRIPT_new(BP_TRANSCRIPT_METHOD_sha256(), "test");
    
    /* 创立公共参数对象,这里最大的批量验证个数为 8 */
    pp = BP_PUB_PARAM_new_by_curve_id(NID_secp256k1, bits, 8);

    if (v == NULL || transcript == NULL || pp == NULL)
        goto err;

    /* 创立该公共参数下的证据对象 */
    witness = BP_WITNESS_new(pp);
    if (witness == NULL)
        goto err;

    for (i = 0; i < len; i++) {if (!BN_lebin2bn((const unsigned char *)&secrets[i], sizeof(secrets[i]), v))
            goto err;

        /* 往证据对象中提交明文证据,因为是 range proof,不须要绑定名称,所以名称能够间接传 NULL */
        if (!BP_WITNESS_commit(witness, NULL, v))
            goto err;
    }

    /* 创立 range proof 上下文对象 */
    ctx = BP_RANGE_CTX_new(pp, witness, transcript);
    if (ctx == NULL)
        goto err;

    /* 创立证实对象 */
    proof = BP_RANGE_PROOF_new_prove(ctx);
    if (proof == NULL)
        goto err;

    /* 验证证实对象是否无效 */
    if (!BP_RANGE_PROOF_verify(ctx, proof))
        goto err;

    ret = 1;
err:
    BP_RANGE_PROOF_free(proof);
    BP_RANGE_CTX_free(ctx);
    BP_WITNESS_free(witness);
    BP_PUB_PARAM_free(pp);
    BP_TRANSCRIPT_free(transcript);
    BN_free(v);

    return ret;
}

int main(int argc, char *argv[])
{
    int i, ret;
    int64_t secrets[16];

    if (argc <= 1 || argc >= sizeof(secrets)/sizeof(secrets[0])) {printf("Invalid parameter!\n");
        return -1;
    }

    printf("number:");
    for (i = 1; i < argc; i++) {secrets[i-1] = atoi(argv[i]);
        printf("%lld", secrets[i-1]);
    }

    /* 这里指定的位数为 16,即 range 范畴为:[0, 65535] */
    ret = range_proofs_test(16, secrets, argc - 1);

    printf("%s range: [0, 65535]\n", ret == 1 ? "in" : "not in");

    return 0;
}

如上代码正文所示,一次残缺的调用波及 5 个数据结构,别离为:

BP_TRANSCRIPT

该数据结构是交互抄本的构造,用来模仿交互式零常识计划中的交互,是 Bulletproofs 为非交互式零常识证实算法的要害,利用了 Fiat-Shamir 变换将其转变为随机预言机模型中的非交互式零常识计划。

  • 创立 / 开释
/*
 * 创立 BP_TRANSCRIPT
 * 参数:*    method:目前仅实现了 sha256 的办法,通过调用 BP_TRANSCRIPT_METHOD_sha256() 取得,后续能够实现其余更高效的办法
 *    label:证实者和验证者的标签 / 标识
 */
BP_TRANSCRIPT *BP_TRANSCRIPT_new(const BP_TRANSCRIPT_METHOD *method,
                                 const char *label);

/*
 * 开释 BP_TRANSCRIPT
 */
void BP_TRANSCRIPT_free(BP_TRANSCRIPT *transcript);

BP_PUB_PARAM

该数据结构用来保留 Bulletproofs 的公共参数,证实者和验证者须要在同一个公共参数下才有意义,否则证实者生成的证实验证者永远无奈验证通过。

  • 创立 / 开释
/*
 * 创立 BP_PUB_PARAM
 * 参数:*    gens_capacity:对于 range proof 来说就是 range 的位数
 *    party_capacity:对于 range proof 来说就是批量证实 / 验证的最大个数
 */
BP_PUB_PARAM *BP_PUB_PARAM_new(const EC_GROUP *group, int gens_capacity,
                               int party_capacity);
BP_PUB_PARAM *BP_PUB_PARAM_new_by_curve_name(const char *curve_name,
                                             int gens_capacity,
                                             int party_capacity);
BP_PUB_PARAM *BP_PUB_PARAM_new_by_curve_id(int curve_id,
                                           int gens_capacity,
                                           int party_capacity);

/* 
 * 开释 BP_PUB_PARAM
 */
void BP_PUB_PARAM_free(BP_PUB_PARAM *pp);
  • 编码 / 解码
/*
 * 编码 BP_PUB_PARAM 成二进制格局,写入 out 指定的内存区域中
 * 参数:*    pp:公共参数对象
 *       out:要写入的内存指针,如果为 NULL 则返回须要的内存大小,用于申请所需的内存
 *    size:out 内存区域大小
 */
size_t BP_PUB_PARAM_encode(const BP_PUB_PARAM *pp, unsigned char *out, size_t size);

/*
 * 解码 BP_PUB_PARAM
 * 参数:*    in:已编码的证实内存指针
 *    size:in 指针内存区域大小
 */
BP_PUB_PARAM *BP_PUB_PARAM_decode(const unsigned char *in, size_t size);

BP_WITNESS

证据数据结构,用来保留明文证据和密文证据,其中明文证据用于 Prove,密文证据用于 Verify。

  • 创立 / 开释
/*
 * 创立 BP_WITNESS
 * 参数:*    pp:公共参数对象
 */
BP_WITNESS *BP_WITNESS_new(const BP_PUB_PARAM *pp);

/*
 * 开释 BP_WITNESS
 */
void BP_WITNESS_free(BP_WITNESS *witness);
  • 提交证据
/*
 * 提交变量到证据中
 * 参数:*    witness:证据对象
 *       name:变量名称,range proof 不须要关注变量名称,设置为 NULL 即可
 *       v:变量值,也就是明文证据值
 */
int BP_WITNESS_commit(BP_WITNESS *witness, const char *name, const BIGNUM *v);
  • 编码 / 解码
/*
 * 编码 BP_WITNESS 成二进制格局,写入 out 指定的内存区域中
 * 参数:*    witness:证据对象
 *       out:要写入的内存指针,如果为 NULL 则返回须要的内存大小,用于申请所需的内存
 *    size:out 内存区域大小
 *    flag:是否编码明文证据的开关,1 为编码,0 为不编码
 */
size_t BP_WITNESS_encode(const BP_WITNESS *witness, unsigned char *out, size_t size, int flag);

/*
 * 解码 BP_WITNESS
 * 参数:*    in:已编码的证据内存指针
 *    size:in 指针内存区域大小
 *    flag:是否解码明文证据的开关,1 为解码,0 为不解码
 */
BP_WITNESS *BP_WITNESS_decode(const unsigned char *in, size_t size, int flag);

BP_RANGE_CTX

Range Proof 操作上下文数据结构。

  • 创立 / 开释
/*
 * 创立 BP_RANGE_CTX
 * 参数:*    pp:公共参数对象
 *    witness:证据对象
 *       transcript:交互抄本对象
 */
BP_RANGE_CTX *BP_RANGE_CTX_new(BP_PUB_PARAM *pp, BP_WITNESS *witness, BP_TRANSCRIPT *transcript);

/*
 * 开释 BP_RANGE_CTX
 */
void BP_RANGE_CTX_free(BP_RANGE_CTX *ctx);

BP_RANGE_PROOF

该数据结构用来保留 Bulletproofs 执行生成证实算法的计算结果,称为证实或者证实对象,由证实者生成,编码后发送给验证者来验证其有效性。

  • 创立 / 开释
/*
 * 创立 BP_RANGE_PROOF
 * 参数:*    pp:公共参数对象
 */
BP_RANGE_PROOF *BP_RANGE_PROOF_new(const BP_PUB_PARAM *pp);

/*
 * 证实并创立 BP_RANGE_PROOF
 * 参数:*    ctx:上下文对象
 */
BP_RANGE_PROOF *BP_RANGE_PROOF_new_prove(BP_RANGE_CTX *ctx);

/*
 * 开释 BP_RANGE_PROOF
 */
void BP_RANGE_PROOF_free(BP_RANGE_PROOF *proof);
  • 编码 / 解码
/*
 * 编码 BP_RANGE_PROOF 成二进制格局,写入 out 指定的内存区域中
 * 参数:*    proof:证实对象
 *       out:要写入的内存指针,如果为 NULL 则返回须要的内存大小,用于申请所需的内存
 *    size:out 内存区域大小
 */
size_t BP_RANGE_PROOF_encode(const BP_RANGE_PROOF *proof, unsigned char *out, size_t size);

/*
 * 解码 BP_RANGE_PROOF
 * 参数:*    in:已编码的证实内存指针
 *    size:in 指针内存区域大小
 */
BP_RANGE_PROOF *BP_RANGE_PROOF_decode(const unsigned char *in, size_t size);
  • 证实 / 验证
/*
 * 证实,执行证实算法并把后果保留到 proof 对象中
 * 参数:*    ctx:上下文对象
 *    proof:证实对象,个别由 BP_RANGE_PROOF_new 创立
 * 返回值:胜利返回 1,否则返回 0
 */
int BP_RANGE_PROOF_prove(BP_RANGE_CTX *ctx, BP_RANGE_PROOF *proof);

/*
 * 验证
 * 参数:*    ctx:上下文对象
 *    proof:证实对象,由证实者生成并发送给验证者来验证
 * 返回值:胜利返回 1,否则返回 0
 */
int BP_RANGE_PROOF_verify(BP_RANGE_CTX *ctx, const BP_RANGE_PROOF *proof);

编译

$ gcc -Wall -g -o range_proof ./range_proof.c -I/opt/tongsuo-bulletproofs/include -L/opt/tongsuo-bulletproofs/lib -lcrypto

将 /opt/tongsuo-bulletproofs 替换成你的铜锁装置目录即可。

运行

$ ./range_proof 11
number: 11 in range: [0, 65535]

$ ./range_proof 11 22
number: 11 22 in range: [0, 65535]

$ ./range_proof 11 22 65535
number: 11 22 65535 in range: [0, 65535]

$ ./range_proof 11 22 65536
number: 11 22 65536 not in range: [0, 65535]

$ ./range_proof 0
number: 0 in range: [0, 65535]

$ ./range_proof 65536
number: 65536 not in range: [0, 65535]

$ ./range_proof 11 22 33 44 55 66 77 88
number: 11 22 33 44 55 66 77 88 in range: [0, 65535]

$ ./range_proof 11 22 33 44 55 66 77 88 99
number: 11 22 33 44 55 66 77 88 99 not in range: [0, 65535]

如上后果所示,含有超出范围的数 (65536) 和超出批量验证个数的输出都验证失败了,其余输出验证胜利。

理解更多 …

铜锁 /Tongsuo Star 一下✨:

https://github.com/Tongsuo-Project/Tongsuo

退出移动版