ECDH-PSI 协议#
算法流程#
算法分为2阶段,第一阶段为握手过程,第二阶段为算法主体,其流程如下:
握手过程#
握手所用的 HandshakeRequest 定义如下:
interconnection/algos/psi.proto#
1message HandshakeRequest {
2
3 // The version of psi handshake message. Start from 1.
4 //
5 // 握手请求版本号
6 int32 version = 1;
7
8 // Supported algorithms (支持的 PSI 算法): ecdh, pcg*, bark-oprf*
9 repeated string supported_algos = 2;
10
11 // Corresponding psi algo parameters proposals.
12 //
13 // 相应的 PSI 算法详细握手参数,与 supported_algos 一一对应
14 repeated google.protobuf.Any algo_params = 3;
15
16 // How many items do I've.
17 //
18 // 待求交的 PSI 数据总量
19 int64 item_num = 4;
20
21 // Usually we need to make partitions for large-scale PSI. This field defines
22 // the number of bucket we've proposed. Note the larger one will be chosen as
23 // the final bucket number.
24 //
25 // 大规模数据(比如十亿)求交需要决定的分桶数,任何一方都可以给出分桶数,最后以大的一方为主。
26 // 未使用
27 int64 bucket_num = 5;
28
29 // Which rank can receive the psi results.
30 //
31 // 确定 PSI 结果获取方。
32 //
33 // NOTES:
34 // `-1`: all parties (所有机构都可以拿到交集结果)
35 // `>= 0`: corresponding rank can get the results (指定机构拿到交集结果)
36 int32 result_to_rank = 7;
37}
HandshakeRequest 主要包括以下信息:
协议版本号
想使用的具体 PSI 算法,比如使用 ECDH-PSI
每类 PSI 算法的详细参数,比如 ECDH-PSI 需要说明具体的椭圆曲线类型,HASH 算法相关参数等
结果可见性说明:结果是A,B都可见,还是只对某一方可见
如果算法是 Ecdh-psi,则 HandshakeRequest 中的 algo_params 字段格式如下:
interconnection/algos/psi.proto#
1// ECDH PSI algorithm parameters proposal.
2//
3// ECDH PSI 算法参数握手请求
4message EcdhPsiParamsProposal {
5 // supported versions,支持的算法版本列表
6 // 当前必须为 1
7 repeated int32 supported_versions = 1;
8
9 // Supported curve types( EC 曲线 ):
10 //
11 // - curve25519;
12 // - sm2;
13 repeated string curves = 2;
14
15 // Supported hash methods( 支持的哈希算法 ):
16 // 与 curves 字段长度相同,元素一一对应
17 //
18 // - sha256;
19 // - sm3;
20 repeated string hash_methods = 3;
21
22 // Nonce for hashing.
23 //
24 // 哈希的额外随机数
25 string nonce = 4;
26}
握手请求的结果 HandshakeResponse 定义如下:
interconnection/algos/psi.proto#
1// The handshake response from peer.
2//
3// 对手的握手决策响应
4message HandshakeResponse {
5 // response header
6 ResponseHeader header = 1;
7
8 // The final algo determined.
9 //
10 // 决策下来的 PSI 算法
11 string algo = 2;
12
13 // The number of items for each party.
14 //
15 // 每一方的待求交总数
16 int64 item_count = 3;
17
18 // The number of bucket.
19 //
20 // 实际使用的分桶数
21 // 未使用
22 int64 bucket_num = 4;
23
24 // The final algorithm parameters.
25 //
26 // 决策出来的算法参数
27 google.protobuf.Any algo_params = 6;
28}
其中 ResponseHeader 定义如下:
interconnection/common/header.proto#
1syntax = "proto3";
2
3package org.interconnection;
4
5// 31100xxx is the white box interconnection code segment
6// 31100xxx 为引擎白盒互联互通号段
7enum ErrorCode {
8 OK = 0;
9
10 GENERIC_ERROR = 31100000;
11 UNEXPECTED_ERROR = 31100001;
12 NETWORK_ERROR = 31100002;
13
14 INVALID_REQUEST = 31100100;
15 INVALID_RESOURCE = 31100101;
16
17 HANDSHAKE_REFUSED = 31100200;
18 UNSUPPORTED_VERSION = 31100201;
19 UNSUPPORTED_ALGO = 31100202;
20 UNSUPPORTED_PARAMS = 31100203;
21}
22
23message ResponseHeader {
24 int32 error_code = 1;
25 string error_msg = 2;
26}
algo_params 定义如下:
interconnection/algos/psi.proto#
1// ECDH PSI parameters that parties has agreed.
2//
3// ECDH PSI 算法结果参数
4message EcdhPsiParamsResult {
5 // The psi version actual used.
6 string version = 1;
7
8 // The curve type actual used.
9 string curve = 2;
10
11 // The chosen hash method.
12 string hash_method = 3;
13
14 // The chosen salt used in hash method, i.e. hash(content || nonce).
15 string nonce = 4;
16}
Protobuf 传输方式#
Protobuf 传输使用《传输层白盒互联互通协议》中的 P2P 传输协议进行传输。其中传输的 key 按照《传输层白盒互联互通协议》中定义的方法生成,value 即为 protobuf 序列化之后的二进制字符串。
算法主体#
算法第二步、第四步使用 EcdhPsiCipherBatch 格式进行传输,EcdhPsiCipherBatch 定义如下:
interconnection/algos/psi.proto#
1// The universal ciphertext for each batch.
2//
3// ECDH PSI 密文传输
4message EcdhPsiCipherBatch {
5
6 // The type hint for each message. (密文类型)
7 //
8 // "enc": the first stage ciphertext
9 //
10 // "dual.enc": the second stage ciphertext
11 //
12 // ECDH PSI 密文阶段类型,主要用来区分一阶段和二阶段的密文.
13 string type = 1;
14
15 // The bucket index. Start from 0.
16 //
17 // Bucket 索引
18 // 未使用
19 int32 bucket_index = 2;
20
21 // The batch index. Start from 0.
22 //
23 // Batch 索引,从 0 开始
24 int32 batch_index = 3;
25
26 // Is last batch flag
27 bool is_last_batch = 4;
28
29 // Count of items in this batch.
30 // count == 0 is allowed for last batch
31 int32 count = 6;
32
33 // The packed all in one ciphertext for this batch.
34 //
35 // The first stage ciphertext takes 256 bits for each ciphertext element.
36 // However, the second stage ciphertext takes 96 bits each. According to PSI
37 // papers, we do not need to send all 256 bit for the final ciphertext. The
38 // number of bits needed to compare is `Log(MN) + 40` given a 40 bits
39 // statistical security parameter. TODO (add paper link here).
40 //
41 // We define each bucket has less than 2^28 items, i.e. about 270 million
42 // (单桶最多 2.7亿) items, which is general enough for various psi algorithms.
43 //
44 // NOTE: we do not use `repeated`` here to save overhead of metadata.
45 bytes ciphertext = 7;
46}
其中 ciphertext 字段用于存放 ECC 上的点,存放方式为所有点依次连续存放,curve25519 每个点长度为 32 Bytes,SM2/secp256k1 使用点压缩编码存放,每个点长度33byte,参见 SEC1。