Python教程

基于RSA隐私求交(PSI)的python 实现

本文主要是介绍基于RSA隐私求交(PSI)的python 实现,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

最近开始调研同态加密实现的PSI,回顾了一下基于RSA的PSI方式,见文章

https://eprint.iacr.org/2009/491.pdfzzi

按自己的理解实现了一个python的RSA隐私求交的流程

流程基本按下图实现:

 为了理解中间“盲化”和哈希的过程,所以没有用现成的RSA加解密方案 而是用gmpy2 库的加速模幂计算方法做了 加解密操作。

from Cryptodome.PublicKey import RSA
import hashlib
import binascii 
import gmpy2
import os


rand_bits = 128

def hash_bignumber(num,method='sha1'):
    '''
        num: an integer 
    '''
    if method == 'sha1':
        hash_obj = hashlib.sha1(str(num).encode('utf-8'))
        digest_hex = hash_obj.hexdigest()
        return int(digest_hex,16)
    
def gen_key():
    key = RSA.generate(1024)
    pk = (key.n,key.e)
    sk = (key.n,key.d)
    return pk,sk


def blind_msg_arr_use_pk(msg_arr, pk):
    msg_hash_number_blind = []
    rand_private_list = [] 
    for item in msg_arr:

        hash_num = hash_bignumber(item)
        hash_num = hash_num % pk[0]

        ra = int(binascii.hexlify(os.urandom(rand_bits)),16)
        cipher_ra = gmpy2.powmod(ra,pk[1],pk[0])
        rand_private_list.append(ra)
        msg_hash_number_blind.append(hash_num*cipher_ra)
    
    return msg_hash_number_blind, rand_private_list
    

def deblind_arr_from_client(hash_arr_blind,sk):
    deblind_hash_arr = []

    for item in hash_arr_blind:
        de_blind_number = gmpy2.powmod(item,sk[1],sk[0])
        deblind_hash_arr.append(de_blind_number)
    return deblind_hash_arr


def enc_and_hash_serverlist(server_list,sk):
    hash_server_list = []
    for item in server_list:
        hash_num = hash_bignumber(item)
        c_hash_num = gmpy2.powmod(hash_num,sk[1],sk[0])
        hash_server_list.append(hash_bignumber(c_hash_num))
    return hash_server_list


def hash_deblind_client_arr(deblind_hash_arr, rand_list, pk):
    db_client = []
    for item,ra in zip(deblind_hash_arr,rand_list):
        ra_inv = gmpy2.invert(ra,pk[0]) # ra*ra_inv == 1 mod n 
        db_client.append(hash_bignumber((item * ra_inv) % pk[0]))
    return db_client


def get_common_elements_idx(db_client,db_server):
    # search out the common elements in O(n^2) complexity
    # return the common elements index in local data list
    common_set_index = []
    for idx in range(len(db_client)):
        rec_a = db_client[idx]
        for rec_b in db_server:
            if rec_a == rec_b:
                common_set_index.append(idx)
    return common_set_index


# Server side:
# RSA key generation and send pk to client
pk,sk = gen_key()


# Client side blind the local array and send to server 
msg_arr_client = [12,3,4,8,10,23]  
blind_arr, rlist = blind_msg_arr_use_pk(msg_arr_client,pk)


# Server side 
# receive the blind arr from client and deblind them with secret key
received_blind_arr = blind_arr.copy()
deblind_hash_arr = deblind_arr_from_client(received_blind_arr,sk)

server_list = [12,3,4,5,1,32,45] #12,3,4,8,10,23
# encrypt and hash the server list 
hashed_server_list = enc_and_hash_serverlist(server_list,sk)
# send the deblind array and hashed list to client


# Client side
# Receive the deblind array and hashed server list
received_deblind_hash_arr = deblind_hash_arr.copy()
db_server = hashed_server_list.copy()

# hash the dblind array

db_client = hash_deblind_client_arr(received_deblind_hash_arr,rlist,pk)
common_index_local_list = get_common_elements_idx(db_client,db_server)


print('The hash of db Client:', db_client)
print('The hash of db Server:', db_server)

for idx, true_id in zip(common_index_local_list,[0,1,2]):
    assert idx == true_id



这篇关于基于RSA隐私求交(PSI)的python 实现的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!