【自制】NetSec作业答案参考

持续更新中,欢迎随时电邮

mdlw@m.scnu.edu.cn

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
2
md5sum good
md5sum evil

实验截图:

在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
    #include<x86intrin.h> // __rdtsc(),不同的环境头文件可能会有所不同
    #include<inttypes.h> // uint64_t

    // 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
2
3
from ctypes import cdll, CDLL  
from ctypes import create_string_buffer
from ctypes import c_int, c_ulonglong,c_char,c_char_p

makefile需增添 -lcrypto 项:

1
2
3
4
ALL:  
gcc -c -fPIC -o hello.o hello.c -lcrypto
gcc -shared -o libhello.so hello.o -lcrypto


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

L=i(p1)L = i(p-1)

L=j(q1)+kL = j(q-1)+k

其中 i,kZ+i,k \in Z_+

也就是说

(p1)L(p-1) \mid L(q1)L(q-1) \nmid L


利用费马小定理,可以构造:

aL=ai(p1)=(ap1)i1 (mod p)a^L = a^{i(p-1)} = (a^{p-1})^i \equiv 1\ (mod\ p)

aL=aj(q1)+k=ak(aq1)jak (mod q)a^L = a^{j(q-1)+k} = a^k(a^{q-1})^j \equiv a^k\ (mod\ q)

其中a是随机整数


由于 k0k \neq 0 ,因此 ak1 mod pa^k \equiv 1\ mod\ p 大概率不成立

于是(以很大概率地)有

paL1p \mid a^L -1q(aL1)q \nmid (a^L - 1)

所以

p=gcd(aL1,N)p = gcd(a^L-1,N)

q=N/qq = N/q

d=xgcd((p1)(q1),e)[2]d = xgcd((p-1)(q-1),e)[2] (此处为sagemath语法)

以此恢复出私钥


那么,回到开头,如何“幸运地”选择出L呢?

Pollard 指出:如果 p-1 是许多小素数的乘积,那么对于一些不是特别大的数h而言,有

p1h!p-1 \mid h!


于是对于每个 h = 2,3,4,… , 计算 gcd(ah!1,N)gcd(a^{h!}-1,N)

(习惯而言,可以选择 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到ϕ(n)1\phi(n)-1之间的任意值,只要gcd(e,ϕ(n))==1gcd(e,\phi(n))==1

但为了保证加密和验签的速度,实际使用的e都很小(多使用3或65537)

总的来说,e的公开意味其不负责整个加解密过程的机密性,因此可以最大限度地增强可用性。


3.私钥d的选择有没有要求?

与e不同,私钥d则要求大约与n同等规模(d>2n/2d>2^{n/2}),因为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
2
openssl genrsa -out privkey.pem 2048
openssl rsa -in privkey.pem -pubout -out pubkey.pem

ECDSA公私钥:

1
2
openssl ecparam -name prime256v1 -genkey -noout -out ecprikey.pem
openssl pkey -in ecprikey.pem -pubout -out ecpub.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
2
3
sudo apt-get install openbsd-inetd -y
sudo apt-get isntall telnetd -y
telnet localhost

如果有反应说明配置成功

telnet 一下 virtual-machine 明显是通的

然后设置默认网关

1
sudo route add default gw 192.168.85.129

可以用以下命令验证

1
netstat -nr

这时候再telnet 一下 virtual-machine 就不行了


virtual-machine:

启用telnet服务

1
2
3
sudo apt-get install openbsd-inetd -y
sudo apt-get isntall telnetd -y
telnet localhost

如果有反应说明配置成功

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的数据


文章作者: 莫折眉
文章链接: https://m0d1.top/2022/03/24/netsechomework/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 M0D1.TOP