保序加密OPE 算法 BCLO09及python仿真

一、简介

        数据库经过加密算法加密后会以密文的形式存在,数据的隐私因此受到加密算法的保护,然而为了保证数据库的可用性,必须要求对密文进行有效的检索查询.

        可搜索查询的加密算法均只容许单一的精准匹配,换句话说,用户的查询请求只能匹配到某个具体密文,而对于更加复杂的查询请求(如范围查询),以上算法都是无效的。而保序加密算法能够解决此问题,所以它适用于数据库的加密需求,允许在密文数据库上进行比较操作。

二、算法描述

        Boldyreva 等人提出了一种利用随机保序函数和超几何分布设计的可证安全的OPE 算法。其根据语义安全的概念定义了 OPE 算法的理想安全状态,并给出了 OPE 算法的安全性证明,即攻击者即使得到全部密文,除了密文的顺序以外,就再也得不到其它任何有用的信息。

1. 随机保序函数和超几何分布的关系

超几何分布 在一个抽球模型中,假若有 N 个球,其中黑球 M 个,则白球 N–M 个,每次不放回地随机抽取一个球。用随机变量 X 表示在抽取的 y 个球中黑球的个数,那么 X=x 的概率为

这里直接使用numpy里面的库:

超几何分布(hypergeometric):
        ----numpy中实现:
            np.random.hypergeometric(ngood,nbad,nsample,size)-->产生size个随机数,每个随机数为在总样本中随机抽取
            nsample个样本后好样本的个数。所有样本由ngood个好样本和nbad个坏样本组成。
 
import numpy as np

# 超几何分布,7个好的3个坏的,摸3个,重复10次,返回好球的个数组成的数组
r = np.random.hypergeometric(7, 3, 3, 10)
print(r)


运行结果:
[2 1 3 3 2 2 3 3 2 2]
2. 保序函数模型

例如下图,横坐标是明文域,纵坐标是密文域,密文域要比明文域大。加密的过程就是,将明文在保证顺序的情况下,随机映射到密文域中。在二位坐标系中就是,这些点的连线是一个单调递增的函数。

3. 保序函数伪代码

论文中的伪代码讲的很详细完全可以复现
在这里插入图片描述

4. 保序函数实例讲解

在这里插入图片描述
密钥表 key_table 是一个保存抽样点的 n×2 矩阵,密钥表初始是空的,随着加密明文越多而增加。在整个加密过程中共用该密钥表,其作用类似于使用同一个随机保序函数 f,使得每次加密都沿着该函数进行。解密过程中,密钥表只作查询使用,并不会有所增加。为了更好理解上述过程,在图 2-6 中给出了详细的加解密过程的例子。

假设明文域(1,…, 100)要映射到密文域(1,…, 1000),现要分别加密 25 和 26 两个值。详细过程如下:
加密值25时,第一步中,把密文域 R 中值 500 传进超几何分布函数 HGD 中,得出抽样值 44>25,则向左进一步缩小明文域 D 和密文域 R 的范围,将抽样点(500, 44)保存到密钥表 key_table,以此重复该过程,到了第七步时明文域只剩值 25,则从对应密文域中随机抽取一个值作为对应的密文。
加密值 26 时,由于前六步均可在密钥表 key_table中找到抽样点,则不需要使用超几何分布函数 HGD,到了第七步,把抽样点(306, 26)存进表中。可以发现,两个连续的明文值所对应的密文值,会分别落在两个连续且不相交的密文区间中,因此算法是保序的。该算法的解密过程类似于加密过程,整个过程中,key_table 只作查询使用

三、python仿真实验

新建一个BCLO09.csv文件,存放密钥表格
再创建一个BCLO09.py文件

import csv
import random

import numpy as np
import pymysql

key_table = "BCLO09.csv"
def HGD(D, R):
    len_D = len(D)
    len_R = len(R)
    y = int(len_R / 2)
    x = np.random.hypergeometric(len_D, len_R, y, size=1)
    a = x[0]
    if x[0] >= len_D:
        a = len_D - 1
    return D[a]

def writeCsv(path, data, modle): #传入变量csv文件的路径和要写入的数据
    with open(path,modle,newline="") as f: # 以写入的方式打开文件,newline="" 可以让数据不隔行写入
        writer_csv=csv.writer(f) #调用csv的writer方法往文件里面写入数据,并赋值给writer_scv变量
        writer_csv.writerow(data) #把数据循环写入到writer_csv变量中

#读取csv文件
def readCsv(path): #传入变量csv文件的路径
    list_one=[]    #定义一个空列表
    with open(path,"r") as f: #以只读的方式打开文件
        read_scv=csv.reader(f) #调用csv的reader方法读取文件并赋值给read_scv变量
        for i in read_scv:
            list_one.append(i) #将读取到的数据追加到list列表里面
    return list_one #返回列表数据


def key_tableIsContain(param):
    list_one = readCsv(key_table)
    if len(list_one) == 0:
        return 0, 0
    flag = 0
    for i in range(len(list_one)):
        if str(int(param)) == list_one[i][0]:
            flag = 1
            return 1, int(list_one[i][1])
    if flag != 1:
        return 0, 0



def Enc2(key_table, D, R, m):
    _D = D
    _R = R
    M = max(D) - min(D) + 1
    N = max(R) - min(R) + 1
    center = int((max(R) + min(R)) / 2)
    iscontain, values = key_tableIsContain(center)
    if iscontain == 1:
        c = values #记录D中的抽样值
        x = values
    else:
        x = HGD(D, R)
        a = []
        a.append(center)
        a.append(x)
        writeCsv(key_table, a ,"a")
    print("区间是D[%d, %d]" % (min(_D), max(_D)))
    print("区间是R[%d, %d]" % (min(_R), max(_R)))
    if M == 1:
        print(m)
        print("区间是R[%d, %d]" % (min(_R), max(_R)))
        # return random.randint(min(R), max(R))
        return str(m) + " " + str(min(R)) + " " + str(max(R))

    if M == 2:
        print(m)
        if min(D) == m:
            print("最后的区间是R(%d, %d]" % (min(_R), center))
            return str(m) + " " + str(min(R)) + " " + str(center)
        else:
            print("最后的区间是R(%d, %d]\n" % (center, max(_R)))
            return str(m) + " " + str(center) + " " + str(max(R))

        # return random.randint(min(R), max(R))



    if m <= x: #左边
        D = []
        for i in range(min(_D), x + 1):
            D.append(i)
        R = []
        for j in range(min(_R), center + 1):
            R.append(j)
    else:  #右边
        D = []
        for i in range(x + 1, max(_D) + 1):
            D.append(i)
        R = []
        for j in range(center + 1, max(_R) + 1):
            R.append(j)
    print("D[%d, %d] 抽样值:%d"%(min(_D), max(_D), x))
    print("R[%d, %d] 中间值:%d \n" % (min(_R), max(_R), center))
    return Enc2(key_table, D, R, m)


def Dnc2(key_table, D, R, m):
    _D = D
    _R = R
    M = max(D) - min(D) + 1
    N = max(R) - min(R) + 1
    center = int((max(R) + min(R)) / 2)
    print("区间是D[%d, %d]" % (min(_D), max(_D)))
    print("区间是R[%d, %d]" % (min(_R), max(_R)))
    if M == 1:
        print(m)
        print("明文是:%d\n区间是R[%d, %d]" % (min(D), min(_R), max(_R)))
        return random.randint(min(R), max(R))
    if M == 2:
        if m <= center:
            print("明文是:%d\n最后的区间是R(%d, %d]" % (min(D), min(_R), center))
        else:
            print("明文是:%d\n最后的区间是R[%d, %d)\n" % (max(D), center, max(_R)))

        return random.randint(min(R), max(R))
    iscontain, values = key_tableIsContain(center)
    if iscontain == 1:
        c = values  # 记录D中的抽样值
        x = values
    else:
        print("可能解密错误!")
        return
        x = HGD(D, R)
        a = []
        a.append(center)
        a.append(x)
        # writeCsv(key_table, a, "a")

    if m <= center:  # 左边
        D = []
        for i in range(min(_D), x + 1):
            D.append(i)
        R = []
        for j in range(min(_R), center + 1):
            R.append(j)
    else:  # 右边
        D = []
        for i in range(x + 1, max(_D) + 1):
            D.append(i)
        R = []
        for j in range(center + 1, max(_R) + 1):
            R.append(j)
    return Dnc2(key_table, D, R, m)



if __name__ == '__main__':
    # searchContentList = searchContent()
    # print(searchContentList)
    # Back()

    while (1):
        print("=================\n"
              "\t1、加密\n"
              "\t2、解密\n"
              "\t3、循环加密\n"
              "=================")
        flag = input("请输入你要操作的编号:")
        if flag == "1":
            D = []
            for i in range(100):
                D.append(i + 1)
            R = []
            for i in range(1000):
                R.append(i + 1)
            m = input("请输入你要加密的数字")
            Enc2(key_table, D, R, int(m))
        if flag == "2":
            D = []
            for i in range(100):
                D.append(i + 1)
            R = []
            for i in range(1000):
                R.append(i + 1)
            m = input("请输入你要解密的数字")
            Dnc2(key_table, D, R, int(m))
        if flag == "3":
            D = []
            result = []
            for i in range(100):
                D.append(i + 1)
            R = []
            for i in range(1000):
                R.append(i + 1)
            for i in range(100):
                result.append(Enc2(key_table, D, R, int(i + 1)))
            for c in range(len(result)):
                print(result[c])




图一图二

四、参考文献

[1]何嘉勇. 保序加密域中的数据库水印算法研究[D].暨南大学,2018.

  • 10
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不染心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值