第一章介绍
古典密码和现代密码的区别:
1、古典密码一般应用于军队和政府
2、现代密码到处都有应用。如身份认证、通过信用卡在互联网上购物,下载已认证的操作系统更新,软件应用安全
密钥加密设置
利用加密消息防止eavesdropping
密钥加密应用场景:
1、共享密钥困难(一般来说在安全的位置现场交换比较好),需要一个安全的密钥协商方案(sharing a key)
2、用户加密一些明文存储在硬盘上,在以后的某个时间点返回加密数据解密密文恢复原始数据。(这里硬盘就是攻击者的通信信道,通过访问硬盘驱动器读取内容进行窃听。用户需要安全的存储密钥。
加密的语法
术语 | 符号 |
---|---|
明文空间 | M M M |
生成密钥 | G e n Gen Gen |
加密过程 | E n c Enc Enc |
解密过程 | D e c Dec Dec |
1、密钥生成算法 G e n Gen Gen是概率算法,输出根据某种分布选择的密钥k
2、加密算法 E n c Enc Enc 用密钥k和明文m作为输入,输出密文c。 E n c k ( m ) Enc_{k}(m) Enck(m)
3、解密算法将密钥k和密文c作为输入,输出明文。
D e c k ( c ) Dec_{k}(c) Deck(c)
加密方案需要满足:
每个通过 G e n Gen Gen输出的密钥 k k k,和每个明文消息 m ∈ M m\in M m∈M,都满足以下公式
D e c k ( E n c k ( m ) ) = m Dec_{k}(Enc_{k}(m))=m Deck(Enck(m))=m
Keys and Kerckhoffs’ principle
- 如果攻击者知道通信双方的 D e c Dec Dec和 k k k。攻击者就能解密任何通信双方传输密文。(因此密钥k要好好保护保密,对除了通信双方的其他人)
- Kerckhoffs提出一定不要要求密码方法是秘密的,它必须能够在不造成麻烦的情况下落入敌人之手。(因此密码算法需要设计的就算窃听者知道所有方案细节,只要攻击者不知道密钥,也依然是安全的)
Kerckhoff’s原则的三个主要论点,第一点是加密算法的安全(保密性)比密钥的安全更难保证。密码算法可以利用逆向工程得到。要保证加密算法的安全是很难实现的。
第二点,改变密钥比替换加密方案更容易。
第三点,对于大规模部署,用统一的加密方案会比较容易。
古典密码
凯撒密码(移位)(比较好理解,把原文移动k位)
Enck(m1 · · · mℓ) = c1 · · · cℓ, where ci = [(mi + k) mod 26]
(穷举法brute force就可以破解)
安全的加密算法应该具有足够大的密钥空间,以使穷举搜索攻击不可行。
足够的密钥空间原则为安全性提供了必要条件,
但还不够。
单字母替代密码算法(密码表)这个可以通过统计词频进行攻击:方法就是统计明文和密文中每个字母出现的频率然后找到对应
shift cipher攻击方法:
原来的brute force 难以自动化攻击,因为对电脑来说判断给定明文是否make sense还是比较难的。(可以说是不可能)
有些明文也不一定是有效英语。
pi是第i个字母的出现频率。如果现在已知密文,qi是密文中i字母的出现频率,如果移位个数是k,那么pi和qi+k的频率就会是相等的。所以通过下面这个公式
通过这个公式可以找到密码表里明文密文的字母对应关系。(这也叫统计攻击)
Vigenere密码(也叫多字母移位密码)
如果是c就移2位,d移3位,以此类推。(相应字母和模26)
因为多字母一位,每个字母都可能对应不同的密文字母,因此用统计攻击可能性就不大了
Vigenere密码的攻击方法:
攻击方法:
1、对于已知明文攻击,只需要知道足够多字母对应的明文
2、对于可选择明文攻击,利用明文aaaaa…就可以求出密钥
3、对于唯密文,假设密钥长度位l,将密文分为l组,
每组密文都是明文的一个shift
每组密文的频率都是相应明文频率的一个shift
先对第一组分析
可以猜测第一位密钥是c(同样每组都这样分析就能攻击成功)
如何确定密钥长度?
在一张长纸条上写密文,再在另一张长纸条上写同样密文。将一张纸放在另一张纸上面,将其中一张纸条移动某个位置。相同的字母标记,找到具有最多相同对数的移位值。
密码实现和破译(C语言版)
今天先写加解密,明天写attack(感觉attack用python写方便一些)
//比较简单的加解密
#include<bits/stdc++.h>
using namespace std;
string encrypt(string plaintext,string key)
{
string ciphertext;
int len=plaintext.size();
for(int i=0,j=0;i<len;i++)
{
ciphertext+=(plaintext[i]-'a'+key[j]-'a')%26+'a';
j++;
}
return ciphertext;
}
string decrypt(string ciphertext,string key)
{
string plaintext;
int len=ciphertext.size();
for(int i=0,j=0;i<len;i++)
{
plaintext+=(ciphertext[i]-key[j]+26)%26+'a';
j++;
}
return plaintext;
}
int main()
{
string plaintext,ciphertext,key;
cout<<"请输入要加密的明文:";
getline(cin,plaintext);
cout<<"请输入密钥:";
getline(cin,key);
cout<<"vigenere加密结果是"<<encrypt(plaintext,key)<<endl;
cout<<"请输入要解密的密文";
getline(cin,ciphertext);
cout<<"vigenere解密结果是"<<decrypt(ciphertext,key)<<endl;
getline(cin,ciphertext);
return 0;
}
拿书上的例子验证一下
要转大写的话直接减去32就行(或者用tolower函数)
#include<bits/stdc++.h>
using namespace std;
string encrypt(string plaintext,string key)
{
string ciphertext;
int len=plaintext.size();
for(int i=0,j=0;i<len;i++)
{
ciphertext+=toupper((plaintext[i]-'a'+key[j]-'a')%26+'a');
j++;
}
return ciphertext;
}
string decrypt(string ciphertext,string key)
{
string plaintext;
int len=ciphertext.size();
for(int i=0,j=0;i<len;i++)
{
plaintext+=(tolower(ciphertext[i])-key[j]+26)%26+'a';
j++;
}
return plaintext;
}
int main()
{
string plaintext,ciphertext,key;
cout<<"请输入要加密的明文:";
getline(cin,plaintext);
cout<<"请输入密钥:";
getline(cin,key);
cout<<"vigenere加密结果是:"<<encrypt(plaintext,key)<<endl;
cout<<"请输入要解密的密文:";
getline(cin,ciphertext);
cout<<"vigenere解密结果是:"<<decrypt(ciphertext,key)<<endl;
getline(cin,ciphertext);
return 0;
}
总结:
因为之前也学过密码学这门课程,所以看第一章的时候还是挺好懂的(古典密码),就相当于复习了一遍,不过之前用的教材是清华大学出版的现代密码学,读英文的有一些新概念,比较有意思,也积累了一些之前不认识的单词。。以前都是用notion记笔记,现在打算开始每天写博客,也是一种监督自己学习的方法吧。还不太熟悉markdown语法,还有之前学的latex又忘记了,所以还折腾了挺久,,,(ps:英语还是read out loudly比较有感觉,如果环境允许)
- encompasses 包含
- adversarial attacks 对抗攻击
- parlance 用语
- canonical 典范
- elucidate 阐述
- stark 鲜明
- proprietary 所有权
- ad hoc 点对点
- extraneous 外来的
- blatantly 公然的