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 # 建立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 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 # 由矩阵M生成Ma的函数 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)

2023-04-06by@qjs13667164495-kBu46&@ChatGPT.Model: gpt-3.5
qjs13667164495-kBu46

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

建立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 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

由矩阵M生成Ma的函数

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)

Avatar
Avatar

代码分析:

  1. matrix_construct(policy_list)

该函数是用来构建访问矩阵的。它接受一个策略列表作为参数,并返回一个访问矩阵。首先,它将每个策略转换为一组AND门矩阵,然后将这些矩阵组合为一个OR门矩阵。最后,它将所有OR门矩阵组合为一个完整的访问矩阵。

  1. matrix_construct_and(list_and)

该函数是用来构建AND门矩阵的。它接受一个策略(即AND门矩阵的行)作为参数,并返回一个对应的AND门矩阵。如果策略只包含一个属性,则返回一个单元素矩阵[[1]]。否则,它将使用一个二元AND门矩阵来合并前两个属性,然后使用该矩阵与后面的属性一个接一个地进行合并,直到得到完整的AND门矩阵。

  1. matrix_construct_or(a, b)

该函数是用来构建OR门矩阵的。它接受两个AND门矩阵作为参数,并返回一个对应的OR门矩阵。它将两个矩阵的第一列合并为一个新的列,并将它们的剩余部分拼接起来以形成新的矩阵。如果其中一个矩阵只有一列,则将其余部分填充为0,以便矩阵的尺寸相同。

  1. Access类

该类封装了访问矩阵及相关操作。在初始化时,它根据传递的策略列表构建访问矩阵,并将其存储在成员变量m_matrix中。它还将策略列表拉平为一个一维数组,以方便后续操作。属性列表也是如此。

  1. secretSharing(access, secret)

该函数实现了秘密分享算法。它接受一个Access对象和一个秘密值作为参数,并返回一个向量λ,该向量将用于生成共享密钥。它首先生成一个随机向量v,然后将访问矩阵m_matrix与v相乘,以获得λ向量。

  1. omegaReconstruct(access)

该函数实现了Omega重构算法,用于从共享密钥中还原出原始密钥。它接受一个Access对象作为参数,并返回一个向量ω。它首先计算Ma向量,然后使用Ma的转置矩阵的伪逆矩阵计算出一个向量。最后,它将该向量四舍五入并返回。

  1. get_ma(m_matrix, policy, att)

该函数是一个辅助函数,用于从访问矩阵m_matrix中提取Ma向量。它接受访问矩阵、策略列表和属性列表作为参数,并返回Ma向量。它将策略列表和属性列表组合起来,然后在访问矩阵中查找相应的行,以提取Ma向量。

  1. 主函数

主函数首先创建一个Access对象,然后使用100作为秘密值进行秘密分享。然后,它使用Omega重构算法从共享密钥中还原出原始密钥,并将其打印出来。

总结:

本篇文章介绍了基于门限加密的秘密分享算法的Python实现。该算法可以将一个秘密值分享给多个用户,只有当满足一定条件时,这些用户才能合作将其还原出来。该算法的实现涉及到一些矩阵

Avatar

运算,包括AND门矩阵和OR门矩阵的构建,以及矩阵的乘法和伪逆矩阵的计算等。此外,还涉及到一些向量的操作,如向量的加、乘和内积等。这些操作都是基于numpy库实现的,可以大大简化代码的编写和调试过程。

qjs13667164495-kBu46

请基于差分隐私通过添加拉普拉斯噪声来改进上述代码,并分析优化效果

Avatar
Avatar

差分隐私是通过在计算结果中添加噪声来保护个人隐私的一种方法。在上述秘密分享算法中,我们可以通过添加拉普拉斯噪声来实现差分隐私。下面是基于差分隐私的改进代码:

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