import numpy as np
def matrix_construct(policy_list):
p_len = len(policy_list)
list_and = []
for i in range(p_len):
list_and.append(matrix_construct_and(policy_list[i]))
return_value = matrix_construct_or(list_and[0], list_and[1])
for i in range(p_len - 2):
return_value = matrix_construct_or(return_value, list_and[i + 2])
return return_value.astype(np.int_)
def matrix_construct_and(list_and):
length = len(list_and)
# 若长度为2,则不进行计算,直接返回这个矩阵
two_item_array = np.array([[1, 1], [0, 1]])
# 虽然输入中已经确定了不可能为1,但还是放在这儿,以方便理解算法
if (length == 1):
return np.array([[1]])
elif (length == 2):
return two_item_array
else:
# 设定返回值
return_value = two_item_array
# 每次循环都是一个大矩阵与单条目矩阵[[1]]进行计算
for i in range(length - 2):
return_temp = np.empty([i + 3, i + 3])
# 生成c_a的过程
c_a = return_value[..., 0]
c_a_temp = list(c_a)
c_a_temp1 = list(c_a)
c_a_temp.append(0)
c_a_temp1.append(1)
c_a = np.array(c_a_temp)
c_a_b = np.array(c_a_temp1)
# 生成r_a的过程
r_a = return_value[..., 1:]
r_a = np.concatenate((r_a, np.zeros([1, (i + 1)])))
# 对各列进行赋值
return_temp[..., 0] = c_a
return_temp[..., 1] = c_a_b
return_temp[..., 2:] = r_a
return_value = return_temp
return return_value
def matrix_construct_or(a, b):
h_len_a = a.shape[0]
h_len_b = b.shape[0]
l_len_a = a.shape[1]
l_len_b = b.shape[1]
# 生成第一列
c_a = a[..., 0]
c_b = b[..., 0]
c_a_b = np.append(c_a, c_b)
# 取得r_a和r_b
r_a = a[..., 1:]
r_b = b[..., 1:]
# 生成要填充的零矩阵
r_a_add = np.zeros([h_len_b, l_len_a - 1])
r_b_add = np.zeros([h_len_a, l_len_b - 1])
# 对r_a进行填充
if l_len_a == 2:
r_a = np.append(r_a, r_a_add)
r_a = r_a.reshape(h_len_a + h_len_b, 1)
else:
r_a = np.concatenate((r_a, r_a_add))
# 对r_b进行填充
if l_len_b == 2:
r_b = np.append(r_b_add, r_b)
r_b = r_b.reshape(h_len_a + h_len_b, 1)
else:
r_b = np.concatenate((r_b_add, r_b))
# 联接r_a和r_b
r_a_b = np.concatenate((r_a, r_b), axis=1)
return_value = np.empty([h_len_a + h_len_b, l_len_a + l_len_b - 1])
return_value[..., 0] = c_a_b
return_value[..., 1:] = r_a_b
return return_value
from gmpy2 import mpz, random_state, mpz_urandomb, mpz_random
import random
import sys
rand = random_state(random.randrange(sys.maxsize))
bits = 128
class Access(object):
def __init__(self, policy_list, att_list):
# 初始化后生成访问矩阵M
self.m_matrix = matrix_construct(policy_list)
# 访问列表要拉平,变成一个一维数组,方便后面操作
self.policy = []
for i in range(len(policy_list)):
self.policy.extend(policy_list[i])
# 相当于用户属性组,即是policy_list中的一行
self.att = att_list
def secretSharing(access, secret):
# lambda向量,有的地方写成向量rho
lambda_vector = []
# 生成随机向量v
v_vector = []
v_vector.append(secret)
count = 0
while (count < access.m_matrix.shape[1] - 1):
v_vector.append(mpz_urandomb(rand, bits - 2))
count = count + 1
# 很简单,矩阵M与向量v相乘,得到lambda向量
lambda_vector = np.matmul(access.m_matrix, np.array(v_vector))
return lambda_vector
def omegaReconstruct(access):
# 得到向量Ma
ma = np.array(get_ma(access.m_matrix, access.policy, access.att))
# Ma的转置
ma_trans = np.array(ma.T)
ma_row = len(ma_trans)
# 向量e=[1,0,0,.....]
e_vector = []
e_vector.append(1)
count = 0
while (count < ma_row - 1):
e_vector.append(0)
count += 1
# 求Ma的转置矩阵的伪逆矩阵
ma_trans_inv = np.linalg.pinv(ma_trans)
# 计算得出omega向量
omega_temp = np.matmul(ma_trans_inv, np.array(e_vector))
omega_vector = []
for i in range(len(ma)):
omega_vector.append(mpz(round(omega_temp[i])))
return omega_vector
def get_ma(m_matrix, policy, att):
str_policy = ''
for pp in policy:
if pp < 10:
str_policy += '000' + str(pp)
elif pp >= 10 & pp < 100:
str_policy += '00' + str(pp)
elif pp >= 100 & pp < 1000:
str_policy += '0' + str(pp)
else:
str_policy += str(pp)
str_att = ''
for aa in att:
if aa < 10:
str_att += '000' + str(aa)
elif aa >= 10 & aa < 100:
str_att += '00' + str(aa)
elif aa >= 100 & aa < 1000:
str_att += '0' + str(aa)
else:
str_att += str(aa)
# 找对应用户属性组在矩阵M中对应的是哪几行
att_index = int((str_policy.find(str_att) + 1) / 4)
att_len = len(att)
ma = []
for i in range(att_len):
ma.append(m_matrix[att_index + i])
return ma
if name == "main":
policy_list = [[1, 3, 4, 6, 8, 9], [1, 3, 4, 6, 8, 9, 34, 56, 67]]
att_list = np.array([1, 3, 4, 6, 8, 9], dtype=np.int_)
ac = Access(policy_list, att_list)
s = mpz(100)
lam_vector = secretSharing(ac, s)
omg_vector = omegaReconstruct(ac)
print(omg_vector)
s_un = np.inner(lam_vector[:6], omg_vector)
print(s_un)
代码分析:
该函数是用来构建访问矩阵的。它接受一个策略列表作为参数,并返回一个访问矩阵。首先,它将每个策略转换为一组AND门矩阵,然后将这些矩阵组合为一个OR门矩阵。最后,它将所有OR门矩阵组合为一个完整的访问矩阵。
该函数是用来构建AND门矩阵的。它接受一个策略(即AND门矩阵的行)作为参数,并返回一个对应的AND门矩阵。如果策略只包含一个属性,则返回一个单元素矩阵[[1]]。否则,它将使用一个二元AND门矩阵来合并前两个属性,然后使用该矩阵与后面的属性一个接一个地进行合并,直到得到完整的AND门矩阵。
该函数是用来构建OR门矩阵的。它接受两个AND门矩阵作为参数,并返回一个对应的OR门矩阵。它将两个矩阵的第一列合并为一个新的列,并将它们的剩余部分拼接起来以形成新的矩阵。如果其中一个矩阵只有一列,则将其余部分填充为0,以便矩阵的尺寸相同。
该类封装了访问矩阵及相关操作。在初始化时,它根据传递的策略列表构建访问矩阵,并将其存储在成员变量m_matrix中。它还将策略列表拉平为一个一维数组,以方便后续操作。属性列表也是如此。
该函数实现了秘密分享算法。它接受一个Access对象和一个秘密值作为参数,并返回一个向量λ,该向量将用于生成共享密钥。它首先生成一个随机向量v,然后将访问矩阵m_matrix与v相乘,以获得λ向量。
该函数实现了Omega重构算法,用于从共享密钥中还原出原始密钥。它接受一个Access对象作为参数,并返回一个向量ω。它首先计算Ma向量,然后使用Ma的转置矩阵的伪逆矩阵计算出一个向量。最后,它将该向量四舍五入并返回。
该函数是一个辅助函数,用于从访问矩阵m_matrix中提取Ma向量。它接受访问矩阵、策略列表和属性列表作为参数,并返回Ma向量。它将策略列表和属性列表组合起来,然后在访问矩阵中查找相应的行,以提取Ma向量。
主函数首先创建一个Access对象,然后使用100作为秘密值进行秘密分享。然后,它使用Omega重构算法从共享密钥中还原出原始密钥,并将其打印出来。
总结:
本篇文章介绍了基于门限加密的秘密分享算法的Python实现。该算法可以将一个秘密值分享给多个用户,只有当满足一定条件时,这些用户才能合作将其还原出来。该算法的实现涉及到一些矩阵
运算,包括AND门矩阵和OR门矩阵的构建,以及矩阵的乘法和伪逆矩阵的计算等。此外,还涉及到一些向量的操作,如向量的加、乘和内积等。这些操作都是基于numpy库实现的,可以大大简化代码的编写和调试过程。
请基于差分隐私通过添加拉普拉斯噪声来改进上述代码,并分析优化效果
差分隐私是通过在计算结果中添加噪声来保护个人隐私的一种方法。在上述秘密分享算法中,我们可以通过添加拉普拉斯噪声来实现差分隐私。下面是基于差分隐私的改进代码:
import numpy as np
from gmpy2 import mpz, random_state, mpz_urandomb, mpz_random
import random
import sys
rand = random_state(random.randrange(sys.maxsize))
bits = 128
epsilon = 1.0 # 隐私预算
# 建立Access对象
class Access(object):
def __init__(self, policy_list, att_list):
# 初始化后生成访问矩阵M
self.m_matrix = matrix_construct(policy_list)
# 访问列表要拉平,变成一个一维数组,方便后面操作
self.policy = []
for i in range(len(policy_list)):
self.policy.extend(policy_list[i])
# 相当于用户属性组,即是policy_list中的一行
self.att = att_list
# 计算与门元素生成的矩阵
def matrix_construct_and(list_and):
length = len(list_and)
# 若长度为2,则不进行计算,直接返回这个矩阵
two_item_array = np.array([[1, 1], [0, 1]])
# 虽然输入中已经确定了不可能为1,但还是放在这儿,以方便理解算法
if (length == 1):
return np.array([[1]])
elif (length == 2):
return two_item_array
else:
# 设定返回值
return_value = two_item_array
# 每次循环都是一个大矩阵与单条目矩阵[[1]]进行计算
for i in range(length - 2):
return_temp = np.empty([i + 3, i + 3])
# 生成c_a的过程
c_a = return_value[..., 0]
c_a_temp = list(c_a)
c_a_temp1 = list(c_a)
c_a_temp.append(0)
c_a_temp1.append(1)
c_a = np.array(c_a_temp)
c_a_b = np.array(c_a_temp1)
# 生成r_a的过程
r_a = return_value[..., 1:]
r_a = np.concatenate((r_a, np.zeros([1, (i + 1)])))
# 对各列进行赋值
return_temp[..., 0] = c_a
return_temp[..., 1] = c_a_b
return_temp[..., 2:] = r_a
return_value = return_temp
return return_value
# 计算或门生成的矩阵
def matrix_construct_or(a, b):
h_len_a = a.shape[0]
h_len_b = b.shape[0]
l_len_a = a.shape[1]
l_len_b = b.shape[1]
# 生成第一列
c_a = a[..., 0]
c_b = b[..., 0]
c_a_b = np.append(c_a, c_b)
# 取得r_a和r_b
r_a = a[..., 1:]
r_b = b[..., 1:]
# 生成要填充的零矩阵
r_a_add = np.zeros([h_len_b, l_len_a - 1])
r_b_add = np.zeros([h_len_a, l_len_b - 1])
# 对r_a进行填充
if l_len_a == 2:
r_a = np.append(r_a, r_a_add)
r_a = r_a.reshape(h_len_a + h_len_b, 1)
else:
r_a = np.concatenate((r_a, r_a_add))
# 对r_b进行填充
if l_len_b == 2:
r_b = np.append(r_b_add, r_b)
r_b = r_b.reshape(h_len_a + h_len_b, 1)
else:
r_b = np.concatenate((r_b_add, r_b))
# 联接r_a和r_b
r_a_b = np.concatenate