Fetching...

-

Just a minute...

关键词:隐私保护,权限管理,身份认证,中国剩余定理,密钥分发,密钥更新。

这个项目的是在2019年寒假期间进行的,4月份在中南大学信息安全作品赛答辩,但是由于功能只实现了主体部分,加之我在台上比较胆怯紧张,所以只获得团队三等奖,但是当时老师们还是对我们鼓励有加,说我们有实实在在在做项目。在此感谢两位搭档与我一起努力,共克难关。看着当时做的答辩PPT和项目代码,依然觉得感受良多。这的确是一次既有收获又有遗憾的项目经历。

选题背景

在密码学课程中,我们的指导老师段老师给了我们很多新颖的idea。其中一条是和群文件分级管理有关的,她分析了一个现象:目前在比较大的QQ群里,往往存在很严重的信息泄露情况。如果我们能在聊天群里面对文件进行分级管理,会不会有更好的效果?

的确,信息泄露现象已经屡见不鲜,前不久在学校举办的天梯赛里面就出现了这样的问题,组委会在公布参赛人员名单的时候竟然把所有参与者的姓名,学院,专业名称,班级,学号,QQ,邮箱和联系电话等资料统统泄露了出来,其中也包括我的资料。我对此感到不满,立即与发布这份名单的同学说清楚这样发布名单的危险。还好她很快认识到自己在隐私保护方面的不足,两三分钟后迅速地把这份报名表撤回了。

被泄露的报名表

虽然一份名单中的信息量不多,对不法分子而言可能还卖不出一份好价钱。但是如果人人都抱着这种随意和侥幸的心态,就有可能导致更多更重要的隐私被一次性泄露,从而带来非常大的危害。

作品功能

经过项目组的讨论和意见交换,分析上述情况出现的原因主要有以下三点:

1.文件的发布者隐私保护意识不强。

2.群里人员鱼龙混杂。

3.群文件明文可见。

对发布者的隐私保护意识的提升,光有宣传,效果是不大的,只有通过设计出一款人性化的软件来使他们在不知不觉中形成这种习惯。而群里人员鱼龙混杂,则主要归因于群成员缺乏身份认证。群文件明文可见,则是由于对群成员缺乏分层管理,导致可拓展性低。

为了保证群文件的安全,我们的应用程序打算做到以下几点:

1.群文件加密保存。

2.群成员实名认证。

3.对群成员进行分级权限管理。

4.提醒管理员注意群文件的安全。

这意味着需要实现如下功能:

1.通过权限分级实现权限管理,控制每个用户所能解密的文件等级,以保证保密级别较高的文件具有比较好的保密性。

2.通过基于CRT的密钥分发系统,具体实现文件的访问控制,使级别较低的人不能解密级别较高的文件

3.通过实名制与重名查询,实现辅助的身份认证

4.当群成员退出或者权限降低后,密钥自动更新,使得退出群组的成员无法再解密群中的文件。

群成员的权限管理该采用什么模型呢?当时我在学操作系统安全,在寒假的预习过程中,我预习到了一种模型,叫做BLP模型,当看到这个模型的思路的什么,我就觉得,它正好可以用在我们项目组研制的软件中,根据BLP模型,我做出了一些调整,最终软件所能实现的分层管理功能就是:任何一个等级的群成员,只能浏览安全等级小于或者等于这个等级的群文件。例如,安全等级为4的用户可以得知安全等级为1,2,3,4的文件的密码(这个用户的私钥可以解密上述四种安全等级文件的会话密钥),而安全等级为4的文件只可以被安全等级为4,5的用户查看(只要这些用户能通过解密相应信息或者这个文件的会话密钥)

而基于CRT的密钥分发技术则是在密码学课程中我十分感兴趣的技术。例如在一个交际系统中,A,B,C,D,E都有自己的私钥,若B,C,D需要在不透露自己的私钥的情况下进行沟通,那么可以生成一个会话密钥并通过CRT技术用B,C,D的私钥进行加密,B,C,D可以通过解密这条消息看到相应的会话密钥,而A,E则不行。这样就实现了一个小范围保密通信协议。

身份认证这方面,主要是重名查询。为免有人冒充群里已有的成员加入,每位成员加入的时候,系统会遍历一遍已有的群成员,如果已经存在该群成员,则系统会出现“Red Alert”,提醒管理员要十分注意核实该申请者的身份。同时每一位入群的成员都将被管理员设置成相应的安全级别。

故作品的关键流程与技术如下:

作品实现

作品最终实现了以下功能:群文件密钥分发,实名制,权限管理,密钥可更新,重名查询。

我的两位队友主要负责聊天软件的制作(Q群界面的模拟和身份认证功能的实现),而我负责关键流程的算法设计和代码实现(权限管理,访问控制和密钥更新)。但是最后由于两部分的代码不太兼容,最后没调通,我就直接在eclipse上面展示关键代码的功能了。

关键代码部分(含注释)实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
import java.math.BigInteger;//用于支持java密钥的大数
import java.util.*;


public class CRT {
;
public static void main(String[] args) {
KEY []key=new KEY[5];
for(int i=0;i<5;i++)
{
key[i]=new KEY(32);//对话密钥一般比用户密钥少,用户密钥需要稍大
System.out.println("初始化用户密钥: key"+(i+1)+"="+key[i].primekey);//用户私钥
}
int rank;//文件等级
MOD m=new MOD();
System.out.println("自动生成模数:"+m.primemod);
try {Thread.sleep(1000);}
catch(Exception e) {};
Scanner cin=new Scanner(System.in);
//某用户传送文件
KEY []Ks=new KEY[5];//生成会话密钥
for(int i=0;i<5;i++)
{
Ks[i]=new KEY(30);//会话密钥要比普通密钥稍小
System.out.println("初始化会话密钥: ks"+(i+1)+"="+Ks[i].primekey);//+"="+Ks[i].primekey
}
try {Thread.sleep(500);}//这一段是为了在答辩时老师能慢慢的看变化,看得更清楚
catch(Exception e) {};
//System.out.println("系统内部生成文件加密密钥中");//测试

KEY []Kr=new KEY[5];
System.out.println("根据文件等级生成传输密钥Kr");
for(int i=0;i<5;i++)
{
//第i+1级文件的CRT
//System.out.println("根据文件等级生成传输密钥Kr"+(i+1));
Kr[i]=Ks[i].CRT(key,m,i+1);//根据CRT生成总密钥Kr,Ks是对应会话密钥,m是模数,(i+1)是等级
System.out.println("Kr"+(i+1)+"="+Kr[i].get());
}
try {Thread.sleep(1000);}
catch(Exception e) {};
//展示CRT分级管理后的效果
System.out.println("测试:各等级用户能得到的密钥——请输入你想看的文件等级:");
rank=cin.nextInt();
for(int i=0;i<5;i++)
{
BigInteger result=Kr[rank-1].get().remainder(key[i].get());
System.out.println("第"+(i+1)+"级用户得到的会话密钥是"+result);
}
int k=2;
while(k>0)
{
System.out.println("新建用户");
User a=new User();
int j=2;
while(j>0)
{
System.out.println("请输入你想看的文件级别:");
rank=cin.nextInt();
BigInteger result=Kr[rank-1].get().remainder(key[a.rank-1].get());
System.out.println("用户得到的密钥是"+result);
System.out.println("测试:第"+rank+"级文件会话密钥:"+Ks[rank-1].primekey);
//System.out.println("是否继续?除y之外任意键退出查看文件并注销用户。");
j--;
try {Thread.sleep(5000);}
catch(Exception e) {};
}
//用户注销,执行析构函数
System.out.println("用户注销,密钥将自动更新");
int userank=a.get();

for(int i=0;i<userank;i++)
{
Ks[i]=new KEY(30);//生成会话密钥
//System.out.println("会话密钥已更新");
key[i]=new KEY(32);
//System.out.println("等级私钥已更新");
System.out.println("更新后的等级密钥: key"+(i+1)+"="+key[i].primekey);
try {Thread.sleep(300);}
catch(Exception e) {};
}
for(int i=0;i<5;i++)
{
//第i+1级文件的CRT
System.out.println("重新根据文件等级生成传输密钥Kr"+(i+1));
Kr[i]=Ks[i].CRT(key,m,i+1);//根据CRT生成总密钥Kr,Ks是对应会话密钥,m是模数,(i+1)是等级
System.out.println("新的Kr"+(i+1)+"="+Kr[i].get());
try {Thread.sleep(100);}
catch(Exception e) {};
}
/*System.out.println("是否继续?除y之外任意键退出。");
String str=cin.toString();
str=cin.toString();
if(str.charAt(0)!='y')
{
break;
}*/
}
k--;
try {Thread.sleep(3000);}
catch(Exception e) {};
}

}
class User
{
int rank;
//用户登录,输入密码,获得用户等级
User()
{
Scanner ci=new Scanner(System.in);
System.out.println("请输入用户等级:");
rank=ci.nextInt();//测试用,手动输入用户等级,貌似有错误输入
}
int get()
{
return rank;
}

}
class MOD
//生成模数
{
BigInteger primemod;
MOD()
{
Random rand=new Random();
byte []rand_byte=new byte[35];
rand.nextBytes(rand_byte);
rand_byte[0]=1;//为了让模数大于密码
BigInteger a=new BigInteger(rand_byte),b=new BigInteger(rand_byte);
primemod=a.multiply(b);
primemod=primemod.nextProbablePrime();
}
BigInteger get()
{
return primemod;
}
}
class KEY
//密钥生成
{
BigInteger primekey;
KEY()
{
Random rand=new Random();
byte []rand_byte=new byte[32];
rand.nextBytes(rand_byte);
BigInteger a=new BigInteger(rand_byte);//随机大正数
a=a.abs();
primekey=a.nextProbablePrime();
}
KEY(int i)
{
Random rand=new Random();
byte []rand_byte=new byte[i];
rand.nextBytes(rand_byte);
BigInteger a=new BigInteger(rand_byte);//随机大正数
a=a.abs();
primekey=a.nextProbablePrime();
}
BigInteger get()//输出
{
return primekey;
}
KEY(BigInteger a)
{
primekey=a;
}
void push(BigInteger b)//修改
{
primekey=b;
}
KEY CRT(KEY key[],MOD m,int rank)
{
KEY Kr=new KEY(BigInteger.ZERO);
BigInteger []x=new BigInteger[5];
for(int i=1;i<=5;i++)//把密钥分发给需要的人
{
if(i<rank)//比如等级是三级的文件,1,2级不能看,密钥填0
{
x[i-1]=BigInteger.ZERO;
}
else
{
x[i-1]=primekey;//Ks[i],即对应的会话密钥
}
}
BigInteger p=m.get();
BigInteger Mn=BigInteger.ONE;
for(int i=0;i<5;i++)
{
Mn=Mn.multiply(key[i].get());
}
BigInteger []W=new BigInteger[5];
for(int i=0;i<5;i++)
{
W[i]=Mn.divide(key[i].get());
}
BigInteger []T=new BigInteger[5];//开辟了数组空间
for(int i=0;i<5;i++)
{
T[i]=W[i].modInverse(key[i].get());
}
BigInteger result=BigInteger.ZERO;
for(int i=0;i<5;i++)
{
result=result.add(x[i].multiply(W[i].multiply(T[i])));
}
result=result.remainder(Mn);//咋变成0了
//result=result.remainder(p);
Kr.push(result);
return Kr;
}
}

在测试中,我们的展示流程是这样的:

初始化群用户密钥并生成每类文件的会话密钥。

自动生成每类等级文件密钥的加密信息。

测试CRT定理对密钥分发的有效性:

每个级别的用户对于某个文件等级的文件,能获取到的密钥(样例文件等级为3):

用户入群后,随意访问文件密钥,但是只能看到安全等级比较低的文件,不能访问安全等级比自己等级高的文件。

密钥更新部分,密钥更新产生了新的会话密钥,老用户不再能使用之前的密钥。(PPT没有截图,具体实现可以看代码)

质疑与争论

我的质疑

在答辩前,我写了一份有关这个项目的优势和劣势的一些分析并交予小组成员一起讨论,主要有如下几点:

1.在鱼龙混杂的qq群中,如果管理员真的愿意耐心的给每一个人和文件分配权限的话,那么权限比较低的人看不到权限比较高的文件。那么如果是权限比较高的人出了问题呢?比如管理员的号被盗了怎么办?

2.我们给他足够高的权限意味着我们足够相信他,但是泄密者不一定是本人,也不一定是前员工,如果只是qq号被攻击者窃取了,那么别人是可以在管理员不知情的情况下获取文件内容的。如果文件内容被获取,那么截图或者下载,总有可能是会泄露的。

3.如果我们实在担心文件的安全,为什么还一定要把文件上传到qq而不通过其他方式分享文件?

4.不可否认,通过入群的认证,离开群后更新密钥和分级管理是可以起到一定保护作用。但这种方式的性价比真的高吗,真的值得吗?

不可否认,我可能想得有点多,但是关于上述几个问题,的确值得商榷,最让我担心的还是项目的性价比和应用前景。

团队总结的遗留问题:

经过一番讨论,我们在答辩过程中提出了如下的不足之处和创新点:

老师的质疑:

项目答辩的时候,老师也问了这个项目的应用前景,他们觉得没有这个必要。因为完全可以建一个小一些的Q群,或者使用更安全的公司内部网络。他们建议,我们把这个问题上升到公司内部文件系统的安全上面去,不然看着觉得很好,但是想着又觉得又有点虚。


2020.4.21随想

有时候人性的弱点带来的危险最大,我之前虽然会看入群验证但很少核实信息是否真实。所以我觉得一个应用,最主要的还是要解决人的问题,方便人的生活,同时自然就能保证安全了。

Related post
Comment
Share
  • ACTF2020密码学部分writeup

    编写的项目文件请参考项目链接。同时欢迎大家访问ACTF2020的所有赛题。喜欢的话请多多资瓷一下,给我们实验室的项目加个Star或者Fork,谢谢。 为了保护服务器的同时不给选手带来更多困难,密码学部分的交互题开了pow算力检测,我也...

    ACTF2020密码学部分writeup
  • 通过python脚本自动插入汇编反调试代码

    研究背景在之前OLLVM项目的研究过程中,我们发现反调试技术对反混淆脚本有一定的干扰作用,如果可以在OLLVM的中间代码中自动化插入反调试代码,那么就可以给OLLVM的代码混淆增加一层保障。 方案分析探讨多种方案以后,我认为最适合在汇...

    通过python脚本自动插入汇编反调试代码
  • 基于门限方案的条形码保密及容错技术

    关键词:门限方案,条形码保密,条形码容错,条形码认证与防伪造。 经历过初期两个小项目的探索,我们项目团队积累了一定的项目研究经验,在老师和16级学长的帮助下,我们把研究方向转到了门限方案的实际应用上。结合市面上用9张合并的条形码提高条...

    基于门限方案的条形码保密及容错技术
  • 2020新年原创脚本-其中的小把戏你清楚吗

    关键词:随机数素数生成,新年祝福小程序。 脚本创作这是我在大年三十写的一个程序,当时我正准备去伯克利交流,但由于疫情的缘故,出国变数增大,所以我就打算通过随机数“未卜先知”。以下就是我的脚本: 12345678910111213141...

    2020新年原创脚本-其中的小把戏你清楚吗
  • 基于CRT的物流信息安全处理方案

    关键词:中国剩余定理,密钥分发技术,隐私保护。 引言在2018年11月份的时候,段老师在密码学课上讲到了密钥分发协议,我当时就觉得这个协议很有意思也很有应用前景。后来老师还很主动地分享了一下它的idea,其中一部分就是有关物流单上的信...

    基于CRT的物流信息安全处理方案
  • 安卓反混淆软件探索-deobf

    关键词:代码混淆,代码反混淆及其原理,代码反混淆软件测试与性能对比。 前言我们的大创项目其实是分两方面进行的,一方面,我们从代码混淆的角度比较各种软件对安卓程序的加固能力;另一方面,我们着重针对OLLVM进行反混淆测试。OLLVM集成...

    安卓反混淆软件探索-deobf
  • 记一次安卓代码加固软件的测试过程

    关键词:代码加固,软件测试,原理分析,过程分析。 在大创项目的实践中,我们对市面上的一些安卓代码加固软件进行了采集,经过搜集,发现了几类代码加固方法并分组进行研究。我发现很多代码加固软件都是对java字节码进行混淆与加固,另外一些则选...

    记一次安卓代码加固软件的测试过程
  • 对OLLVM代码加固技术的改进

    1.反静态调试反静态调试可以通过花指令,代码加密,代码加壳等方式实现。 请看图1所示的一段反调试代码: ​ 图1 花指...

    对OLLVM代码加固技术的改进
  • OLLVM代码加固机制分析

    我们通过自己编写测试代码,再用OLLVM的不同指令进行加固,并逆向查看加固效果,加深对代码加固机理的了解。OLLVM目前提供的功能包括控制流平坦化(fla指令),指令替代(sub指令),代码虚拟化(bcf指令)以及虚假控制流(obf指...

    OLLVM代码加固机制分析
  • 对音频缓存加密的探讨

    关键词:缓存解密,批量自动执行脚本,版权保护相关建议。 前段时间,某音乐被爆其缓存文件只使用了简单的异或加密,且容易得到加密密钥为0xa3。原文链接点击这里。以下是我的延伸探讨。 1.对音频缓存的批量解密攻击抱着好奇的心理,我把手机...

    对音频缓存加密的探讨
Please check the parameter of comment in config.yml of hexo-theme-Annie!