.NET中的DES对称加密详解
des算法一般有两个关键点,第一个是加密模式,第二个是数据补位,加密模式的主要意义就是,加密算法是按块进行加密的,例如 des ,是 64bit 一个块的进行加密,就是每次加密 8 个字节,因此每次输入八个字节的明文输出八个字节密文,如果是 16 个字节,那么分成两个块依次进行加密,问题就出现在这里,如果明文是 1234567812345678,分块分别进行加密,那么加密的结果类似“c4132737962c519c c4132737962c519c”,可以看出明文的规律,这就是 ecb 加密模式,密文可以看出明文的规律;为了解决这个问题,有了其他的加密模式:cbc 加密模式(密码分组连接),cfb加密模式(密码反馈模式),ofb加密模式(输出反馈模式)cbc 是要求给一个初始化的向量,然后将每个输出与该向量作运算,并将运算的结果作为下一个加密块的初始化向量,cfb 和 ofb 则不需要提供初始化向量,直接将密码或者输出作为初始化向量进行运算;这样就避免了明文的规律出现在密文中;当然缺点是解密时需要保证密文的正确性,如果网络传输时发生了一部分错误,则后面的解密结果就可能是错误的;(ecb模式仅影响传输错误的那个块。密码算法基本上都是分组(按快)进行加密的,如果密文长度不是刚刚好可以进行分组,怎么办?只能进行填充。
加密算法常见的有ecb模式和cbc模式:
第一种电子密本方式(ecb)
ecb模式:电子密本方式,就是将数据按照8个字节一段进行des加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,则补足8个字节(注意:这里就涉及到数据补位了)进行计算,之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。将明文分成n个64比特分组,如果明文长度不是64比特的倍数,则在明文末尾填充适当数目的规定符号。对明文组用给定的密钥分别进行加密,行密文c=(c0,c1,……,cn-1)其中ci=des(k,xi),i=0,1,…..,n-1。 这是java封装的des算法的默认模式.
第二种密文分组链接方式(cbc)
密文分组链接方式,在cbc方式下,每个明文组xi在加密前与先一组密文按位模二加后,再送到des加密,cbc方式克服了ecb方式报内组重的缺点,但由于明文组加密前与一组密文有关,因此前一组密文的错误会传播到下一组。 这是.net封装的des算法的默认模式,它比较麻烦,加密步骤如下:
1、首先将数据按照8个字节一组进行分组得到d1d2……dn(若数据不是8的整数倍,就涉及到数据补位了)
2、第一组数据d1与向量i异或后的结果进行des加密得到第一组密文c1(注意:这里有向量i的说法,ecb模式下没有使用向量i)
3、第二组数据d2与第一组的加密结果c1异或以后的结果进行des加密,得到第二组密文c2
4、之后的数据以此类推,得到cn
5、按顺序连为c1c2c3……cn即为加密结果。
第三种密文反馈方式(cfb),可用于序列密码
明文x=(x0,x1,……,xn-1),其中xi由t个比特组成0 第四种输出反馈方式(ofb),可用于序列密码
与cfb唯一不同的是ofb是直接取des输出的t个比特,而不是取密文的t个比特,其余都与cfb相同。但它取的是des的输出,所以它克服了cfb的密文错误传播的缺点
数据补位一般有nopadding和pkcs7padding(java中是pkcs5padding)填充方式,pkcs7padding和pkcs5padding实际只是协议不一样,根据相关资料说明:pkcs5padding明确定义了加密块是8字节,pkcs7padding加密快可以是1-255之间。但是封装的des算法默认都是8字节,所以可以认为他们一样。数据补位实际是在数据不满8字节的倍数,才补充到8字节的倍数的填充过程。
nopadding填充方式:算法本身不填充,比如.net的padding提供了有none,zeros方式,分别为不填充和填充0的方式。
pkcs7padding(pkcs5padding)填充方式:为.net和java的默认填充方式,对加密数据字节长度对8取余为r,如r大于0,则补8-r个字节,字节为8-r的值;如果r等于0,则补8个字节8.比如:
加密字符串为为aaa,则补位为aaa55555;加密字符串为bbbbbb,则补位为bbbbbb22;加密字符串为cccccccc,则补位为cccccccc88888888.
.net中的des加密
对于.net,框架在system.security.cryptography命名空间下提供了descryptoserviceprovider作为system.security.cryptography.des加密解密的包装接口,它提供了如下的4个方法:
public override icryptotransform createdecryptor(byte[] rgbkey, byte[] rgbiv)
public override icryptotransform createencryptor(byte[] rgbkey, byte[] rgbiv)
public override void generateiv()
public override void generatekey()
从.net类库封装情况,加解密需要传入一个key和iv向量。而且key必须为8字节的数据,否则会直接抛异常出来,当使用ecb模式下,不管传入什么iv向量,加密结果都一样。