主题:密码学基础(部分):经典古典密码选、流密码、对称加密(部分)
内容:
目录
目录
1、经典古典密码选
1.1替换(替代)密码
如凯撒密码,就是将明文里的每一个元素/字母,如果是二进制则是0和1(bit)都映射给另外一个元素,这个映射规则或者映射就是密码,如(A->D和3)
替代密码的建立一般有如下几步:
1、先建立一个替换表;
2、加密时将需要加密的明文依次通过查表,替换为相应的字符。明文字符被逐个替换后,生成无任何意义的字符串,即密文;
解密时则利用对应的逆替换表,将需要解密的密文依次通过查表,替换为相应的字符即可恢复出明文。替代密码的密钥就是其替换表。
根据密码算法加解密时使用替换表多少,替代密码又可分为单表替代密码和多表替代密码。
根据密码学的名词,替代密码的密钥则是一个或者多个替换表。
分析替代密码算法,先从凯撒密码开始:
加密::C=E(3,m)=m+3(mode 26) 0<=m<=25;
解密::M=D(3,C)=C-3(mode 26) 0<=C<=25;
凯撒密码是单表替换,那么可以实现每个元素都有其自己的偏移量的“维吉尼亚密码”则是多表替换。
我们将偏移量计做K,则每个元素都偏移量K1、K2.......Kn构成“K表”,K表可以循环使用,即,例如明文有8个字母,而k表只有7位,则第八个字母需要偏移时,读取K1进行偏移。
加解密公式如下:
上面的K=(K1、K2........Kn)
维吉尼亚密码是在凯撒密码基础上产生的一种加密方法,它将凯撒密码的全部25种位移排序为一张表,与原字母序列共同组成26行及26列的字母表。另外,维吉尼亚密码必须有一个密钥,这个密钥由字母组成,最少一个,最多可与明文字母数量相等。维吉尼亚密码加密方法示例如下:
明文:I've got it.
密钥:ok密文:W'fs qcd wd.
首先,密钥长度需要与明文长度相同,如果少于明文长度,则重复拼接直到相同(也就是上面提到的“k表循环使用”)。本例中,明文长度为8个字母(非字母均被忽略),密钥会被程序补全为“okokokok”。现在根据如下维吉尼亚密码表格进行加密:
明文第一个字母是“I”,密钥第一个字母是“o”,在表格中找到“I”列与“o”行相交点,字母“W”就是密文第一个字母;同理,“v”列与“k”行交点字母是“F”;“e”列与“o”行交点字母是“S”……
维吉尼亚密码只对字母进行加密,不区分大小写,若文本中出现非字母字符会原样保留。
如果输入多行文本,每行是单独加密的。
值得注意的是:
维吉尼亚密码的偏移时从0「A」开始的!!!!
1.2换位密码:
将明文中每一个元素都重新排列,并没有改变明文中的任何信息,只是次序混乱,导致词不达意无法理解。
1.1和1.2相比较时,可以发现转位式密码只是改变明文中单元的位置,而单元本身没有转变;相反,替换式密码只是转换单元,但密文中单元的位置没有改变。
常见的换位密码是栅栏密码。
加密原理:把要加密的信息交替排成两行,再将下边的行连接到上边行的尾部。
简单就直接上图了。不拖时间。
1.3乘积密码(Product Cipher)
通过结合两个或更多置换的方式制造比单独的加密方式更安全的密码以抵抗密码分析。乘积密码往往结合的是简单的置换/替换算法。
1 .1、1 .2两种加密方法都有其缺陷:替代密码的明文只要内容量较大,就有可能遭到频度分析法的攻击,而置换密码的缺点是明文量不能大,量大则会导致置换方式易被发现。
补充:古典密码统计分析
不介绍具体方法。
理论基础是柯克霍夫原则(Kerckhoffs准则)
由奥古斯特·柯克霍夫在19世纪提出:密码系统应该就算被所有人知道系统的运作步骤,仍然是安全的。克劳德·艾尔伍德·香农有句近似的话「敌人知道系统」,称为香农公理。
同时,即使密码系统的任何细节已为人悉知,只要密匙(key)未泄漏,它也应是安全的。这关乎我们下边讲的流密码的安全性。因此,密码分析的重点在获取密钥。
在一定条件下,古典密码体制中的任何一种都可以被破译。弗吉尼亚密码、置换密码等对已知明文攻击的抵抗力比较脆弱。即使用唯密文攻击,大多数古典密码体制都是容易被攻破。由于古典密码多用于保护用英文语言表达的信息,英文语言的统计特征是攻击古代密码的有力工具。这是因为,大多数古典密码体制都不能很好的隐藏明文消息的统计特征。
对单表替代密码、多表替代密码和 Hill 密码来介绍利用英文语言的统计特征和密码特点,运用为密文攻击或已知明文攻击等方式破译古典密码的基本方法。——转自Lois大佬的博文:《密码学入门》
2、流密码
2.1、流密码的基本思想
流密码也称序列密码,属于对称密码的一种,加密和解密双方使用相同伪随机加密数据流(pseudo-random stream)作为密钥,明文数据每次与密钥数据流顺次对应加密,得到密文数据流。实践中数据通常是一个bit并用xor操作加密。
流密码是建立在香农的“一次一密”(cryptographic one-time pad)安全理论上的,香农同时证明了一个无法被破译的密码系统的密钥必须有以下特征:完全随机;不能重复使用;保密;和明文一样长。因此,具有均匀分布的离散无记忆随机数列作为密文理论上是不可破译的。这保证了流密码的安全性。
基本术语:
密钥:k
产生一个密钥流:z=z0 z1…;
明文串:x=x0 x1 x2…;
加密: y=y0 y1 y2 … =Ez0(x0)Ez1(x1)Ez2(x2)…;
流密码的原理如上图所示。
我们可以看到,流密码的特点之一就是加解密双方同用一个密钥。密钥k是整个流密码加解密的核心,是唯一不能泄漏的信息,如密文、加密方式等等都可以在公共信道上传播,但是k只能在确保安全的私人信道传输。
其中密钥流生成器需要解释一下工作原理。其一我们需要厘清的概念是,密钥k和密钥流z是不同的,完全不是一个事物。在明确这个前提后,我们来用一条表达式解释密钥流生成器。
密钥流发生器 f:zi=f(k,σi);
其中σi是加密器中的记忆元件(存储器)在时刻i的状态,f是由密钥k和σi产生的函数。
利用不断变化的加密变换对明文消息进行 逐bit的加密。流密码的滚动密钥 z0 = f ( k,σ 0 ) 由函数 f、密钥 k 和指定的初态σ 0 完全确定。此后, 由于输入加密器的明文可能影响加密器中内部记忆元件的存储状态, 因而σ i ( i > 0)可能依赖于 k,σ 0 , x0 , x1 , ⋯, xi - 1 等参数。
设计密码体制的关键问题是设计产生密钥序列的方式,但是因为真正的具有均匀分布的随机序列是不可能重复产生的. 密钥序列长(至少与明文序列一样长), 其管理(存储、分配)难.
2.2流密码的两种模型
为了解决上述的问题,我们研究了两种流密码模型,包括:SSC同步流密码以及SSSC自同步流密码,SSC的特点是,产生密钥序列的算法与密文明文无关,而SSSC产生密钥序列的算法却与以前的密文有关。
对于同步流密码而言,只要有同样的种子序列与相同的初始状态就可以产生相同的密钥序列,这就要求着使用同步流密码进行加密的信息收发双方要保持精确的同步才能正确的加解密信息。
同步流密码容易检测插入、删除、重播等主动攻击,没有差错传播。
在一个同步流密码当中,加密/解密过程中要使用同一个密钥在一样的位置上操作。如若在传输当中密文字符(或位)存在插入或删除造成同步丢掉,则解密会不成功,此时对同步进行重建只有利用其他的加密技术,才可以将解密不断地进行下去。重置同步的技术包括:再次初始化,在密文的规则间隙之中标记特别的记号;若明文含有充足的冗余度,则就能对密钥流的全部可能偏移进行尝试。
对于无差错传播,则因为在传输期间,一个密文字符的变化(不是插入与删除)仅仅对恢复该字符的变化造成影响,对后继字符不可能会有影响。【概念:无或有限的差错传播是指一个部分(比如一个比特或一个字节)的错误不会影响其他的部分的正常解密或者只会影响有限的范围】
除了SSC与SSSC之外,我们还介绍一个模型:异或流密码。
所谓异或流密码,即是加密解密主要使用异或的运算。
即:对于明文序列:m=m1,m2,m3......;密钥序列:z=z1,z2,z3......;密文序列c=c1,c2,c3......存在这样的关系:
有些内容还未完善,姑且写出来:
RC4算法
久负盛名的RC4算法。它属于对称密码里的流密码,密钥长度可变(指种子密钥),面向bit操作。以一个足够强大的S表(S-box)为基础,对表进行非线性变换,产生密钥流。
首先来简述一下RC4的原理。
RC4是一个简洁的加密方式,要素主要包括初始化算法(KSA)和子密码生成算法(PRGA)两大部分。假设S-box的长度为256,密钥长度为Len。
第一步是初始化S-box
1、对S表进行线性填充,一般长度为256个bit(内容一般为0~255);
2、用种子密钥填充另一个256bit的K-box;【规则:种子密钥长度可变,如长度恰为256bit则直接填充,若小于256则循环使用直到k完全被赋值】
3、用K-box对S-box进行初始置换。
#include <iostream>
#include <cmath>
using namespace std;
//KSAKSAKSA31112112022
int main(){
int N=0;
cin>>N;
int SS[N],KK[N];
for(int i=0;i<N;i++){
SS[i]=i;
}
for(int i=0;i<N;i++){
cin>>KK[i];
}
int j=0;
for(int i=0;i<N;i++){
j=(j+SS[i]+KK[i])%7;
swap(SS[i],SS[j]);
cout<<j<<" "<<endl;
for(int t=0;t<N;t++){
cout<<SS[t];
}
cout<<endl;
}
return 0;
}
KSA的算法大概如上图所示。
第二步是子密钥生成算法
i,j=0;
for r=0 to len do //r为明文长度,r字节
i=(i+1) mod 7;
j=(j+S[i])mod 7;
swap(S[i],S[j]);
t=(S[i]+S[j])mod 7;
k[r]=S[t];