DES是一种对称加密(Data Encryption Standard)算法于年得到美国政府的正式许可是一种用位密钥来加密位数据的方法一般密码长度为个字节其中位加密密钥每个第位都用作奇偶校验
DES算法一般有两个关键点第一个是加密模式第二个是数据补位加密模式的主要意义就是加密算法是按块进行加密的例如 DES 是 Bit 一个块的进行加密就是每次加密 个字节因此每次输入八个字节的明文输出八个字节密文如果是 个字节那么分成两个块依次进行加密问题就出现在这里如果明文是 分块分别进行加密那么加密的结果类似CCC CCC可以看出明文的规律这就是 ECB 加密模式密文可以看出明文的规律为了解决这个问题有了其他的加密模式CBC 加密模式(密码分组连接)CFB加密模式(密码反馈模式)OFB加密模式(输出反馈模式)CBC 是要求给一个初始化的向量然后将每个输出与该向量作运算并将运算的结果作为下一个加密块的初始化向量CFB 和 OFB 则不需要提供初始化向量直接将密码或者输出作为初始化向量进行运算这样就避免了明文的规律出现在密文中当然缺点是解密时需要保证密文的正确性如果网络传输时发生了一部分错误则后面的解密结果就可能是错误的(ECB模式仅影响传输错误的那个块密码算法基本上都是分组(按快)进行加密的如果密文长度不是刚刚好可以进行分组怎么办?只能进行填充
加密算法常见的有ECB模式和CBC模式
第一种电子密本方式(ECB)
ECB模式电子密本方式就是将数据按照个字节一段进行DES加密或解密得到一段个字节的密文或者明文最后一段不足个字节则补足个字节(注意这里就涉及到数据补位了)进行计算之后按照顺序将计算所得的数据连在一起即可各段数据之间互不影响将明文分成n个比特分组如果明文长度不是比特的倍数则在明文末尾填充适当数目的规定符号对明文组用给定的密钥分别进行加密行密文C=(CC……Cn)其中Ci=DES(Kxi)i=……n 这是Java封装的DES算法的默认模式
第二种密文分组链接方式(CBC)
密文分组链接方式在CBC方式下每个明文组xi在加密前与先一组密文按位模二加后再送到DES加密CBC方式克服了ECB方式报内组重的缺点但由于明文组加密前与一组密文有关因此前一组密文的错误会传播到下一组 这是NET封装的DES算法的默认模式它比较麻烦加密步骤如下
首先将数据按照个字节一组进行分组得到DD……Dn(若数据不是的整数倍就涉及到数据补位了)
第一组数据D与向量I异或后的结果进行DES加密得到第一组密文C(注意这里有向量I的说法ECB模式下没有使用向量I)
第二组数据D与第一组的加密结果C异或以后的结果进行DES加密得到第二组密文C
之后的数据以此类推得到Cn
按顺序连为CCC……Cn即为加密结果
第三种密文反馈方式(CFB)可用于序列密码
明文X=(xx……xn)其中xi由t个比特组成 第四种输出反馈方式(OFB)可用于序列密码
与CFB唯一不同的是OFB是直接取DES输出的t个比特而不是取密文的t个比特其余都与CFB相同但它取的是DES的输出所以它克服了CFB的密文错误传播的缺点
数据补位一般有NoPadding和PKCSPadding(Java中是PKCSPadding)填充方式PKCSPadding和PKCSPadding实际只是协议不一样根据相关资料说明PKCSPadding明确定义了加密块是字节PKCSPadding加密快可以是之间但是封装的DES算法默认都是字节所以可以认为他们一样数据补位实际是在数据不满字节的倍数才补充到字节的倍数的填充过程
NoPadding填充方式算法本身不填充比如NET的padding提供了有NoneZeros方式分别为不填充和填充的方式
PKCSPadding(PKCSPadding)填充方式为NET和Java的默认填充方式对加密数据字节长度对取余为r如r大于则补r个字节字节为r的值如果r等于则补个字节比如
加密字符串为为AAA则补位为AAA;加密字符串为BBBBBB则补位为BBBBBB;加密字符串为CCCCCCCC则补位为CCCCCCCC
NET中的DES加密
对于NET框架在SystemSecurityCryptography命名空间下提供了DESCryptoServiceProvider作为SystemSecurityCryptographyDES加密解密的包装接口它提供了如下的个方法
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必须为字节的数据否则会直接抛异常出来当使用ECB模式下不管传入什么IV向量加密结果都一样