参考链接: https://blog.csdn.net/qq_32318629/article/details/108378081
参考论文:A Traceable and Revocable Ciphertext-Policy
Attribute-based Encryption Scheme Based
on Privacy Protection
KEK树
构建一棵完全二叉树,二叉树的叶子节点是系统中的用户。
KEK完全二叉树和最小覆盖集的性质:
完全二叉树
python实现
class Node(object):
"""节点类"""
def __init__(self, id, parent=None, lchild=None, rchild=None, isleaf=False):
self.u = None
self.id = id
self.parent = parent
self.lchild = lchild
self.rchild = rchild
self.isleaf = isleaf
def getId(self):
return self.id
def getParent(self):
return self.parent
def getLchild(self):
return self.lchild
def getRchild(self):
return self.rchild
from math import *
from node import *
class Tree(object):
"""树类"""
def __init__(self, root = None):
self.root = root
def creatTree(self, U):
#有bug,该函数创建的是满二叉树,用户个数必须为2^n个,而不是完全二叉树
'''
:param U:系統中用戶列表
:return:返回树的根节点和用户身份编号字典
'''
n = len(U)
N = 2 * n - 1
nodelist = []
identity_list = {}
nodelist.append(Node(0))
#计算树的深度
depth = floor(log2(N)) + 1
#依据节点个数算出树的深度,然后创建节点,并存在nodelist列表中
for i in range(1, depth + 1):
#树的每一层的节点实例化
#每一层节点的编号为(2^(i-1),2^i-1)
min = (int)(pow(2, i - 1))
max = (int)(pow(2, i))
for j in range(min, max):
node = Node(j)
if i == depth:
node.isleaf = True
identity_list[U[j-min]] = j
nodelist.append(node)
#print("len:", len(nodelist))
#树的节点编号从1开始,将树中的节点依据二叉树的性质连接
for i in range(1, len(nodelist)):
node = nodelist[i]
if(i != 1):
node.parent = nodelist[(int)(i / 2)]
#print(i,node.parent.id)
if node.isleaf == False:
node.lchild = nodelist[2 * i]
node.rchild = nodelist[2 * i + 1]
self.root = nodelist[1]
return (nodelist[1], identity_list)
def creatTree2(self, U):
'''
创建完全二叉树
:param U:系統中用戶列表
:return:返回树的根节点和用户身份编号字典
'''
n = len(U)
N = 2 * n - 1
# 存储节点的列表
nodelist = [Node(0)]
identity_list = {}
for i in range(1, N+1):
node = Node(i)
nodelist.append(node)
for i in range(1, N+1):
# 非叶非父母节点
if i != 1 and 2 * i + 1 <= N:
nodelist[i].lchild = nodelist[2 * i]
nodelist[i].rchild = nodelist[2 * i + 1]
nodelist[i].parent = nodelist[(int)(i / 2)]
# 根节点,无父母
if i == 1:
nodelist[i].lchild = nodelist[2 * i]
nodelist[i].rchild = nodelist[2 * i + 1]
# 叶结点
if i != 1 and 2 * i > N:
nodelist[i].parent = nodelist[(int)(i / 2)]
nodelist[i].isleaf = True
nodelist[i].u = U[i - n]
identity_list[U[i - n]] = i
self.root = nodelist[1]
return identity_list
#返回叶子节点到根节点的路径
def getPath(self, leaf):
# 返回路径ID列表
if leaf == None:
return []
path = []
temp = leaf
while(temp.parent != None):
path.insert(0,temp.id)
#print("temp.id", temp.id)
#print("temp.parent", temp.parent.id)
temp = temp.parent
path.insert(0,temp.id)
return path
def getPath2(self, leaf):
# 返回路径节点列表
if leaf == None:
return []
path = []
temp = leaf
while(temp.parent != None):
# 每次在开头插入元素
path.insert(0, temp)
temp = temp.parent
path.insert(0, temp)
return path
def SearchU(self, Root, u):
if Root == None:
return
if Root.isleaf:
if Root.u == u:
res = Root.id
return [res, Root]
#use = self.SearchU(Root.lchild, u)
if self.SearchU(Root.lchild, u) == None:
return self.SearchU(Root.rchild, u)
else:
return self.SearchU(Root.lchild, u)
'''查找覆盖集, 先找到撤销列表中所有节点的路径集合,然后判断生成最小覆盖集'''
def cover(tree, reList):
minCover = []
revocable = []
# 把撤销列表中用户的路径节点添加到revocable中
for node in reList:
tempList = tree.getPath2(node)
#print(tempList)
for i in tempList:
if i not in revocable:
revocable.append(i)
# 对于revocable中的节点,如果节点左孩子不在撤销列表则将左孩子添加到mincover列表中,右孩子同理。
for i in revocable:
if i.isleaf == True:
continue
if i.lchild not in revocable:
minCover.append(i.lchild.id)
if i.rchild not in revocable:
minCover.append(i.rchild.id)
# 如果revocable为空,即系统中没有撤销用户,那么此时根节点就是最小覆盖集。
if len(revocable) == 0:
minCover.append(1)
return minCover
使用charm-crypto复现论文A Traceable and Revocable Ciphertext-Policy
Attribute-based Encryption Scheme Based
on Privacy Protection完整代码。地址:https://github.com/xuekema/Revocable-CPABE-KEK_Tree