ECDH-PSI 协议#

算法流程#

算法分为2阶段,第一阶段为握手过程,第二阶段为算法主体,其流程如下:

../_images/ecdh-psi-flow.png

握手过程#

握手所用的 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 主要包括以下信息:

  1. 协议版本号

  2. 想使用的具体 PSI 算法,比如使用 ECDH-PSI

  3. 每类 PSI 算法的详细参数,比如 ECDH-PSI 需要说明具体的椭圆曲线类型,HASH 算法相关参数等

  4. 结果可见性说明:结果是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 序列化之后的二进制字符串。

算法主体#

../_images/ecdh-psi-algo.png

算法第二步、第四步使用 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