持续更新中,欢迎随时电邮
MD5 Collision Demo
MD5碰撞实验,实测碰撞用时不超过10分钟
详细过程见以下链接
Peter Selinger: MD5 Collision Demo (dal.ca)
先下载
evilize-0.2.tar.gz
然后
1 | tar zxf evilize-0.2.tar.gz |
然后
1 | cd evilize-0.2 |
然后
1 | make -j8 |
然后
1 | gcc hello-erase.c goodevil.o -o hello-erase |
然后
1 | ./evilize hello-erase -i |
得到一串初始化向量,我这里是
0x00a35f0c 0x35b2a90f 0xff63ea8c 0x6cc7d22e
然后(要把自己得到的向量替换掉我这里的)
1 | ./md5coll 0x00a35f0c 0x35b2a90f 0xff63ea8c 0x6cc7d22e > init.txt |
然后
1 | ./evilize hello-erase -c init.txt -g good -e evil |
最后检查一下得到的两个可执行文件的md5值,显然碰撞成功
1 | md5sum good |
实验截图:
在make之后修改程序hello-erase.c ,可以看出碰撞也能成功
(这里我把输出改了
DES,AES,TEA and SM4 Performance analysis
题目:
- 从网上搜集DES,AES,TEA和SM4的源码,并在本地环境编译,编写一个小程序,测试四种加密算法的加密速度。
- 从测试过程中观察,各个加密算法中对性能影响最大的子模块(函数)是哪个?
先给出我的结论(仅供参考
对于第一个问题,加密速度由快到慢 TEA > AES > SM4 > DES (其中SM4与DES的快慢关系存疑)
对于第二个问题,AES性能影响最大的模块是列混淆;DES性能影响最大的模块是Feistel函数;对于SM4,性能影响最大的是T变换;TEA加密结构简单,故不进行分析。
我的实验过程(仅供参考
-
源码
我是去github找的,起初找了很多代码(不管能不能跑起来),但发现很头疼的一点是即使是相同的对称密码,不同人的代码加密速度也会有天差地别,罔论四个对称密码的比较了;所幸的是,我们有openssl库,可以相对公平地比较 SM4,DES,AES三者的加密速度(TEA不在该库中,不过我们可以断言TEA是四个中最快的——因为它的结构实在太简洁了)。我最后选用的代码使用了openssl的EVP(指envelope encryption,封装好的加密函数)系列加密函数来比较性能。 -
性能分析
我们需要获取加密消耗的CPU cycle来得出结论。听从 McLsk 建议,用的是__rdtsc()函数,见下:
1
2
3
4
5
6
7
8
9
10
11
12
13//VMware Ubuntu 18
// balabala
uint64_t start,end; //预先声明好,等下赋值的时候可以节省时间
int main(){
//balabala
start = __rdtsc();
Encrypt(balabala);
end = __rdtsc();
printf("balabala's time:%ld\n",end - start);
} -
子模块对比
选用openssl的EVP系列函数显然无法对比对称密码内部模块的性能,万事不决StackOverflow,借助该网站的一个问答speed of aes implementation我很快知道了对AES性能影响最大的模块(即最耗时的模块):列混淆;但我找不到其他密码的答案了,考虑到针对单个密码本身不需要考虑公平的问题(我们可以断言一个糟糕\优秀的加密实现,其内部每个模块都是程度相同的糟糕\优秀,但一个糟糕\优秀的加密实现不代表另外三个实现同等糟糕\优秀,这是个逻辑问题),这时候就可以随便找代码了——只要它的耦合度合适,测试各模块性能(理论上)就是轻而易举的事情(最好找那些有注释的,这样不用看源码就知道哪里在干嘛),测试所用的性能分析函数同上。 -
得出结论
见上。
OpenSSL and Command-line
1)根据课本3.7章节中的逐步完成各项OpenSSL编译与命令行实验;
2)做实验并写实验报告:修改3.7.2/3.7.3中的cryptoDemo.cpp为enfile.py(python3),从命令行接收3个字符串类型的参数:参数1、参数2、参数3。参数1=enc/dec分别表示加密或解密,参数2为待加密/解密的文件名,参数3为加解密所用密钥key
命令行参数
我用的是 argparse 库,具体使用方式可以百度
1 | import argparse |
PY下的OpenSSL
我在pyopenssl下找不到任何有关AES的api,我怀疑根本就没有在py下的实现;除此之外,我们可以用python调用clib来实现这个过程。
这里是Crypto库的实现。
1 | from Crypto.Cipher import AES |
clib的食用方式请参考以下blog↓
python调用clib的两种方法 - 莹的博客 (izualzhy.cn)
1 | from ctypes import cdll, CDLL |
makefile需增添 -lcrypto 项:
1 | ALL: |
The Selection of RSA Parameters
1.p、q的选择必须是安全素数(p = 2m+1,q = 2n+1,其中m,n是素数),为什么必须这样?
令 N = pq
下面介绍 Pollard’s p-1 Factorization Algorithm:
假设幸运地得到了具有如下性质的正整数L
其中
也就是说
且
利用费马小定理,可以构造:
其中a是随机整数
由于 ,因此 大概率不成立
于是(以很大概率地)有
且
所以
(此处为sagemath语法)
以此恢复出私钥
那么,回到开头,如何“幸运地”选择出L呢?
Pollard 指出:如果 p-1 是许多小素数的乘积,那么对于一些不是特别大的数h而言,有
于是对于每个 h = 2,3,4,… , 计算
(习惯而言,可以选择 a = 2)
如果 gcd == 1 ,选择下一个h
如果 gcd == N ,选择另一个a
如果 1 < gcd < N ,结束循环
(该算法需要优化,但在此按下不表)
回到问题本身,因为要使得 p-1 不成为许多小素数的乘积,所以 p = 2m+1 , 其中 m 是一个大素数(q也如此)
P.S. 参考自 An Introduction to Mathematical Cryptography
2.公钥e的选择有没有要求?
公开指数e,原则上可以是3到之间的任意值,只要。
但为了保证加密和验签的速度,实际使用的e都很小(多使用3或65537)
总的来说,e的公开意味其不负责整个加解密过程的机密性,因此可以最大限度地增强可用性。
3.私钥d的选择有没有要求?
与e不同,私钥d则要求大约与n同等规模(),因为d是秘密的,必须要保证其不可预测,所以不能被限制在一个很小的范围。
P.S. 2、3 参考自 Serious Cryptography : A Practical Introduction to Modern Encryption
4.加密、签名对于密钥有何不同的保护要求?
(1)签名密钥对的管理
签名密钥对由签名私钥和验证公钥组成。 签名私钥是发送方身份的证明,具有日常生活中公章、私章的效力。为保证其惟一性, 签名私钥绝对不能够做备份和存档,丢失后只需重新生成新的密钥对。验证公钥需要存档, 用于验证旧的数字签名。 用做数字签名的这一对密钥一般可以有较长的生命期。
(2)加密密钥对的管理
加密密钥对由加密公钥和解密私钥组成。 为防止密钥丢失时数据无法恢复,解密私钥应该进行备份,同时还可能需要进行存档, 以便能在任何时候解密历史密文数据。加密公钥则无需备份和存档,加密公钥丢失时,只需 重新生成密钥对即可。 这种密钥应该频繁更换,故加密密钥对的生命周期较短。 不难看出,这两对密钥的密钥管理要求存在互相冲突的地方,因此,必须针对不同的用 途使用不同的密钥对。尽管有的公钥体制算法如RSA,既可以用于加密,又可以用于签名, 但由于这两对密钥在管理上截然不同的要求,在使用中仍然必须为用户配置两对密钥:其一 用于数字签名,另一用于加密。而采用一对密钥,既用于加密,又用于签名,这种做法是不安 全的。
P.S. 参考:https://blog.csdn.net/gotohbu/article/details/4328066
5.安装OpenSSL,给自己签发一对RSA和ECDSA公私钥,尝试以下操作:
签发的动作由CA完成
所以我们需要先构造(虚构)一个CA:
首先生成CA的private key(即ca.key)
1 | openssl genrsa -aes128 -out ca.key 2048 |
输入以上命令后会让你设置口令,openssl会通过该口令(生成密钥使用aes128)对private key进行加密
#可选项:去除ca.key里的口令
1 | openssl rsa -in ca.key -out ca.key |
用私钥ca.key生成自签名证书ca.crt
(其实是用私钥生成公钥,然后把公钥和一些配置信息包装成证书,最后自签名)
1 | openssl req -new -x509 -key ca.key -out ca.crt -days 365 |
然后生成用户的RSA公私钥:
1 | openssl genrsa -out privkey.pem 2048 |
ECDSA公私钥:
1 | openssl ecparam -name prime256v1 -genkey -noout -out ecprikey.pem |
以下以rsa为例
生成证书请求文件csr,用来请求CA给你一张数字证书
(这里的-key privkey.pem项一方面为了生成公钥,另一方面为了给csr签名)
1 | openssl req -new -key privkey.pem -out rsa.csr |
CA为csr签发证书rsa.crt
注意设置序列号与有效期
1 | openssl x509 -req -in rsa.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out rsa.crt -days 365 |
以上,签发的RSA证书(包含公钥)与对应的私钥已经准备好了,可以开搞。
对一个exe文件生成签名/验签
注:私钥签名,公钥验签
RSA:
直接签名会因文件太大而无法完成,可以先生成摘要然后对摘要签名:
1 | openssl dgst -sign privkey.pem -sha256 -out bigorlittle_rsa.sign bigorlittle.exe |
验签过程:
首先,需要用ca.crt验证rsa.crt的真实性
1 | openssl verify -CAfile ca.crt rsa.crt |
然后,从rsa.crt中提取公钥(可以vim查看rsapub.pem与之前生成的pubkey.pem是否一致,直接hash会不一致原因是证书提取的公钥内含证书信息而直接使用私钥生成的没有)
1 | openssl x509 -outform PEM -in rsa.crt -pubkey -out rsapub.pem |
最后,用公钥验签
1 | openssl dgst -verify pubkey.pem -sha256 -signature bigorlittle.sign bigorlittle.exe |
ECDSA类似
对一个xml文件进行加密/解密
P.S. ECDSA不能用于加解密
生成新的RSA公私钥对,申请新的证书(签名与加密的钥对不能共用)
用RSA加密:
首先,需要用ca.crt验证xml.crt的真实性
然后,从xml.crt中提取公钥
最后用公钥加密文件
1 | openssl rsautl -encrypt -in testxml.xml -inkey xmlpubkey.pem -pubin -out teslxml.en |
私钥解密:
直接用私钥解密
1 | openssl rsautl -decrypt -in teslxml.en -inkey xmlprivkey.pem -out testxml.de |
sha256一致
与另外一个同学进行双向通信,安全传输一个xml文件
我用的方法是:用 基于openssl实现https双向身份认证及安全通信_tutu-hu的博客 openssl实现https 的方法进行加密参数协商与口令的安全传输,之后Bob就可以在不安全的信道传输加密后的xml文件了
Alice使用协商好的加密算法与参数以及口令(用来生成对称密钥),解密xml
- 实验环境:
WSL 扮演 Bob
VMware - Ubuntu 扮演 Alice
虚构一个CA
- 前期准备:
安装openssl相关以及安装:
1 | sudo apt-get install libncurses-dev |
然后互相ping一下看看网络通不通
用之前提到的方法生成ca.key, ca.crt, server.key, server.crt, client.key, client.crt
(分别是CA、Alice、Bob的私钥与证书)
分别编译好ssl_client.c和ssl_server.c
- 密钥参数协商
Alice
1 | ./server 7838 1 server.crt server.key ca.crt |
Bob (此处是Alice IP地址)
1 | ./client 192.168.85.132 7838 client.crt client.key ca.crt |
其中口令(password)是logicmd(重复了3次)
加密与解密文件:
传输文件在不安全的信道中即可,这里不进行展示。
hash值:
Firewall
1.基于Linux虚拟机,安装、配置pfSense
实验环境:
VMware Workstation 16
一台虚拟机配置成pfsense,双网卡(LAN:192.168.235.130、WAN:192.168.85.129)
一台Ubuntu虚拟机布置在LAN(192.168.235.0)网段下,用户名是virtual-machine
一台Ubuntu虚拟机布置在WAN(192.168.85.0)网段下,用户名是virtual-machine-2
(a) 设置单层防火墙,限制外部主机访问localhost的全部端口;
virtual-machine 是(防火墙)内部(的)主机,即localhost
virtual-machine-2是(防火墙)外部(的)主机
pfsense配置:https://blog.csdn.net/qq_44851362/article/details/105414918
进入pfsense的web页面
配置Firewall / Rule / Floating
点击右下角的add
Action选择Block或者Reject,Interface全选(按住Ctrl然后分别点击WAN与LAN),Protocol选择TCP/UDP(其实选any也行,但这里为了验证),Destination选择in
Destination选择从21到8080(同样为了验证)
配置完成点Save然后回到Rules界面点击Apply Changes
虚拟机配置
virtual-machine-2:
启用telnet服务
1 | sudo apt-get install openbsd-inetd -y |
如果有反应说明配置成功
telnet 一下 virtual-machine 明显是通的
然后设置默认网关
1 | sudo route add default gw 192.168.85.129 |
可以用以下命令验证
1 | netstat -nr |
这时候再telnet 一下 virtual-machine 就不行了
virtual-machine:
启用telnet服务
1 | sudo apt-get install openbsd-inetd -y |
如果有反应说明配置成功
telnet 一下 virtual-machine-2 明显是通的
然后设置默认网关
1 | sudo route add default gw 192.168.235.130 |
可以用以下命令验证
1 | netstat -nr |
最终结果:
virtual-machine-2视图
可以发现在配置默认网关后telnet virtual-machine 不通了
说明报文经过防火墙后被block了
如果不配置默认网关为pfsense的WAN口,报文(大概是)直接通过虚拟交换机(192.168.85.2)转发,不经过防火墙
virtual-machine视图
可以发现在配置默认网关后telnet virtual-machine 依然通,说明防火墙是单向的
(b) 有条件的情况下,配置双层防火墙模式(一个虚拟机配置mysql,一个作为web服务器,在两者之间尝试设置一个防火墙);
无条件
2.安装 Snort,与pfSense配合成为IDS工作模式。
根据
在pfSense中配置使用Snort | 鐵血男兒的BLOG (pfschina.org)
配置就行了
结果:
注意不要启用Block Offenders选项,否则会变成IPS
IPSec
1. 基于Windows的管理工具,在两个主机(或者虚拟机与主机,或两个虚拟机)之间配置端到端IPSec安全(AH模式,ESP模式,AH+ESP模式)
环境:五台 windows Server 2003 虚拟机
部署方式参考《网络信息安全》(曾凡平编著)4.42 从P82-P87
除此之外,还需要配置五台机器(Client A, Client B, Server A, Server B, Router)的IP地址、子网掩码与默认网关
以及路由器的“路由及远程访问”(自定义配置 -> LAN路由 即可)
路由器需要安装 旧版wireshark
a) 抓取部署前的ping数据包,与部署IPSec后的进行对比。
部署前ping不通(没有 reply报文),并且数据包没有加密
部署后(应用筛选器操作的AH+ESP并指派)可以ping通,且包已被加密(Info处看不到有用信息)
随机打开某个包查看,发现有AH与ESP的数据
b) 有条件的情况下,对IPSec保护的AH、ESP模式进行对比。
AH模式:
因为AH不支持加密,所以抓到的包是明文(Info处显示是ping包)
随机打开某个包查看,发现只有AH的数据
ESP模式:
Info处看不到有用信息
随机打开某个包查看,发现只有ESP的数据