64位密钥经过置换选择1、循环左移、置换选择2等变换,产生16个48位长的子密钥。子密钥的产生过程如图
具体方法如下:
置换选择1:64位的密钥分为8个字节,每个字节的前7位是真正的密钥位,第8位作为奇偶校验位,将64位密钥中去掉8个奇偶校验位,并将其余56位密钥位打乱重排,且将前28位作为C0,后28位作为D0。
置换选择2:将Ci和Di合并成一个56位的中间数据,从中选择出一个48位的子密钥Ki。
由于DES的运算是对合运算,所以解密和加密可共用同一个运算,只是子密钥使用的顺序不同。把64位密文当作明文输入,而且第一次解密迭代使用子密钥K16,第二次解密迭代使用子密钥K15,依次类推,第十六次解密迭代使用子密钥K1,最后输出便是64位明文。
用Python实现DES加解密
from Cryptodome.Cipher import DES import binascii key = b'abcdeggh; #key的的长度必须为8字节 des = DES.new(key, DES.MODE_ECB) #ECB模式 tsxt = 'ms08067.com' text = text + (8 - (len(text)%8)) * '=' encrypt_text = des.encrypt(text.encode())) encryptResul = binascii.b2a_hex(encrypt_text) print(text) peint(encryptResult) from Cryptodome.Cipher import DES import binascii key = b'abcdefgh' #key的长度必须为8字节 des = DES.new(key,DES.MODE_ECB) #ECB模式 encryptResult = b' b81fcb047936afb76487dda463334767' encrypto_text = binascii. a2b_hex (encry ptResult) decryptResult = des, decrypt (encrypto_t ext) print (decryptResult)
DES加密方式存在许多安全问题。例如,密钥较短可被穷举攻击,存在弱密钥和半弱密钥等。因此,美国NIST在1999年发布了一个新版本的DES标准3DES。3DES加密算法的密钥长度为168位,能够抵抗穷举攻击,并且3DES底层加密算法与DES相同,许多现有的DES软硬件产品都能方便地实现3DES,因此在使用上也较为方便。
在CTF比赛中往往会利用DES加密算法的密钥较短、弱密钥等安全问题获取flag。一些白帽子在渗透测试过程中会发现拦截的数据包被DES加密,此时,可以考虑DES为对称加密算法,在JavaScript前端代码中寻找相应的key值进行破译。
AES加密算法
简介
AES(Advanced Encryption Standard,高级加密标准)的出现,是因为以前使用的DES算法密钥长度较短,已经不适应当今数据加密安全性的要求,因此2000年10月2日,美国政府宣布将比利时密码学家Joan Daemen和Vincent Rijmen提出的密码算法RIJNDAEL作为高级加密标准。2001年11月26日,美国政府正式颁布AES为美国国家标准(编号为FIST PUBS 197)。这是密码史上的又一个重要事件。目前,AES已经被一些国际标准化组织,如OSO、IETF、IEEE 802.11等采纳,作为标准。
原理
AES是一个迭代的、分组密码加密方式,可以使用128、192和256位密钥。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换(permutation)和替换(substitution)输入数据,加之算法本身复杂的加密过程,使得该算法成为数据加密领域的主流。
在AES算法中,每一次变换操作产生的中间结果称为状态。将状态表示为二维字节数组(每个元素为一个字节),包括4行,Nb列。Nb等于数据块长度除以32。例如,数据块长度为128时,Nb=4;数据块长度为192时,Nb=6。同理,密钥也可表示为二维字节数组(每个元素为一个字节),包括4行,Nk列。Nk等于密钥块长度除以32。
圈密钥根据圈密钥产生算法由用户密钥产生。圈密钥加密由密钥扩展和圈密钥选择两步完成。首先将用户的密钥进行密钥扩展,再从扩展密钥中选出圈密钥。第一个圈密钥由扩展密钥中的前Nb个字组成,第二个圈密钥由接下来的Nb个字组成,以此类推。最后获得的圈密钥位总数为数据块长度与圈数加l的乘积。
RIJNDAEL算法的迭代圈数Nr由Nb和Nk共同决定,可根据下表回去相应的Nr的值。
RIJNDAEL算法迭代圈数N
AES加密算法的轮函数采用代替/置换网络结构,包括S盒变换(ByteSub)、行移位变换(ShiftRow)、列混合变换(MixColumn)、圈密钥加变换(AddRoundKey)。下面介绍各种变换方式。
1. S盒变换
S盒变换是按字节进行的代替变换,是作用在状态中每个字节上的一种非线性字节变换。首先将字节的值用它的乘法逆来代替,然后将获取的值按式 进行仿射变换。
2. 行移位变换
行移位变换对状态行进行循环移位。在行移位变换中,状态的后三行以不同的移位值循环左移。第0行不移位,第1行向左移动C1字节,第2行向左移动C2字节,第3行向左移动C3字节,移位表如下图所示。
3.列混合变换
列混合变换是对状态的列进行混合变换。把状态中的每一列看作GF(28)上的多项式,并与一个固定多项式c(x)相乘,然后与多项式x4+1进行取模运算,其中c(x)可表示为
4.圈密钥加变换
圈密钥加变换是利用圈密钥对状态进行模2相加的变换。圈密钥被简单地异或到状态中去。其中,圈密钥长度等于数据块长度。
综上所述
AES加密算法由三部分组成:初始圈密钥加、Nr-l圈的标准轮函数、最后一圈的非标准轮函数。
用Python实现AES加解密
接下来将通过Cryptodome库函数实现对字符串进行AES加密。由于AES为分组密码的加密方式,其工作模式有五种:ECB、CBC、CTR、CFB、OFB。下面将以ECB模式为例,对字符串进行AES加密和解密。
from Cryptodome. Cipher import AES import binascii key = b' abcdefghabcdefgh' # key的长度须为8字节 text = 'ms08067. com #被加密的数据需要为8字节的倍数 text = text + (16 - (len(text) % 16)) *'=' aes = AES. new (key, AES. MODE_ECB) #ECB模式 >>>encrypto_text = aes. encrypt (text. encode()) >>>encryptResult = binascii. b2a_hex (encryp to_text) >>>print(text) print (encryptResult) from Cryptodome. Cipher import AES import binascii key = b' abcdefghabcdefgh' #key的长度须为8字节 encryptResult = b' 51d23f9cab201da377c925ac526c4901' aes = AES. new (key, AES. MODE_ECB) #ECB模式 encrypto_text = binascii. a2b_hex (encryp tResult) decryptResult = aes. decrypt (encrypto_te xt print (decryptResult)
AES密码是一个非对称密码体制,它的解密要比加密复杂和费时。解密优化算法在没有增加存储空间的基础上,以列变化为基础进行处理,节约了处理时间。AES是高级数据加密算法,无论是安全性、效率,还是密钥的灵活性等方面,都优于DES数据加密算法,在今后将逐步代替DES,被广泛应用。
MD5加密算法
简介
MD5(Message-Digest Algorithm,信息摘要算法)是一种被广泛使用的密码散列函数,由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。该算法不仅能对信息管理系统加密,还广泛应用于计算机、数据安全传输、数字签名认证等安全领域。由于该算法具有某些不可逆特征,在加密应用上有较好的安全性。
原理
MD5是以512位的分组来处理输入的信息,并且将每一分组又划分成16个32位的子分组,经过了一系列的处理后,算法的输出由四个32位的分组组成,将这四个32位的分组结合后将生成一个128位的散列值。下图为md5加密算法流程。
步骤
1.填充在MD5算法中,首先需要将信息进行填充,使其位长对512求余后的结果等于448。即使符合上述条件,也必须进行填充。因此,信息的位长将被扩展至N×512+448,N是一个非负整数。计算原始消息的长度(不包含填充部分),并且附加到填充位与消息之后。该长度值为64位二进制数表示的填充前信息的长度。
2.信息分组首先将数据按每512位为一组进行分组,如图6-14所示,再把每组里面分成16个32位数据。
3.初始化变量初始化四个链接变量A、B、C、D,它们都是32位的数字,这些链接变量的初始十六进制数值如下所示,低字节在前:
当设置好这四个链接变量后,就开始进入算法的四轮循环运算。将上面四个链接变量复制到另外四个变量中:A到a,B到b,C到c,D到d。
主循环有四轮,每轮循环都很相似,每一轮进行16次操作。每次操作对a、b、c和d的其中三个进行一次非线性函数运算,然后将所得结果加上第四个变量、信息的一个子分组和一个常数,再将所得结果左移一个不确定的数,并加上a、b、c、d之一。
以下是四轮循环中用到的四个非线性函数(每轮一个):
所有这些操作完成之后,将A、B、C、D分别加上a、b、c、d,然后用下一分组的数据继续运行算法,最后MD5算法产生128位的输出是A、B、C、D的级联,其中低字节始于A,高字节终于D。至此,整个MD5算法处理结束。
用Python实现MD5加密
用Python实现MD5加密时用到的是hashlib模块,可以通过hashlib标准库使用多种Hash算法,如SHA1、SHA224、SHA256、SHA384、SHA512和MD5算法等。下面是通过调用hashlib模块对字符串进行MD5加密的简单实例:
from hashlib import md5 def encrypt_md5 (s) : new_md5 = md5 () #创建md5对象 new_md5. update (s. encode (encoding='utf8')) return new_md5. hexdigest () if_name_main == ' _name_ ' : print (encrypt_md5 (' ms08067. com' ))
虽然MD5为单向Hash加密,且不可逆,但根据鸽巢原理,MD5算法所产生的32位输出所能够表示的空间大小为1632,即当样本大于1632时就会产生Hash碰撞。由这一结论可知,我们可以生成大量密码样本的Hash,得到密码和Hash值的一一对应关系,然后根据这个对应关系反查,就可以得到Hash值所对应的密码。在互联网应用方面,有相当多的用户使用弱密码,因此可以根据统计规律建立简单密码所对应的MD5值表,从而得到使用简单密码的用户账户。
鉴于存在以上安全性问题,可以在用户密码被创建时生成一个随机字符串(称之为Salt)与用户口令连接在一起,然后再用散列函数对这个字符串进行MD5加密。如果Salt值的数目足够大,它实际上就消除了对常用口令采用的字典式破解,因为攻击者不可能在数据库中存储那么多Salt和用户密码组合后的MD5值。当然,更加安全的做法是,给每个密码设置一个随机的Salt值,这样即使通过暴力枚举破解了一个用户的密码,也很难再破解其他用户的密码。