3DES加密算法简析
2016-01-26 22:51
253 查看
3DES加密算法并非什么新的加密算法,而是DES算法的另一种模式。是现在比较常用的一种对称加密算法,比起DES来说安全性更高。该算法的加解密过程分别是对明文/密文数据进行三次DES加密或解密,得到相应的密文或明文。假设EK()和DK()分别表示DES的加密和解密函数,P表示明文,C表示密文,那么加解密的公式如下:
加密:C = EK3( DK2( EK1(P) ) ) 即对明文数据进行,加密 --> 解密 --> 加密的过程,最后得到密文数据
解密:P = DK1( EK2( DK3(C) ) ) 即对密文数据进行,解密 --> 加密 --> 解密的过程,最后得到明文数据
其中:K1表示3DES中第一个8字节密钥,K2表示第二个8字节密钥,K3表示第三个8字节密钥,通常情况下,3DES的密钥为双倍长密钥(若不知道双倍长,可参考博主的密钥分算算法文章中的解释),即K1对应KL(左8字节),K2对应KR(右8字节),K3对应KL(左8字节)。
由于DES加解密算法是每8个字节作为一个加解密数据块,因此在实现该算法时,需要对数据进行分块和补位(即最后不足8字节时,要补足8字节)。Java本身提供的API中NoPadding,Zeros填充和PKCS5Padding。假设我们要对9个字节长度的数据进行加密,则其对应的填充说明如下:
ZerosPadding
无数据的字节全部被填充为0
第一块:F0 F1 F2 F3 F4 F5 F6 F7
第二块:F8 0 0 0 0 0 0 0
PKCS5Padding
每个被填充的字节都记录了被填充的长度
第一块:F0 F1 F2 F3 F4 F5 F6 F7
第二块:F8 07 07 07 07 07 07 07
DES的具体算法过程很复杂,实话说我也不懂,我只能借用Android和iOS里面自带的API去实现3DES的过程,其具体代码如下:
Android代码
iOS代码
加密:C = EK3( DK2( EK1(P) ) ) 即对明文数据进行,加密 --> 解密 --> 加密的过程,最后得到密文数据
解密:P = DK1( EK2( DK3(C) ) ) 即对密文数据进行,解密 --> 加密 --> 解密的过程,最后得到明文数据
其中:K1表示3DES中第一个8字节密钥,K2表示第二个8字节密钥,K3表示第三个8字节密钥,通常情况下,3DES的密钥为双倍长密钥(若不知道双倍长,可参考博主的密钥分算算法文章中的解释),即K1对应KL(左8字节),K2对应KR(右8字节),K3对应KL(左8字节)。
由于DES加解密算法是每8个字节作为一个加解密数据块,因此在实现该算法时,需要对数据进行分块和补位(即最后不足8字节时,要补足8字节)。Java本身提供的API中NoPadding,Zeros填充和PKCS5Padding。假设我们要对9个字节长度的数据进行加密,则其对应的填充说明如下:
ZerosPadding
无数据的字节全部被填充为0
第一块:F0 F1 F2 F3 F4 F5 F6 F7
第二块:F8 0 0 0 0 0 0 0
PKCS5Padding
每个被填充的字节都记录了被填充的长度
第一块:F0 F1 F2 F3 F4 F5 F6 F7
第二块:F8 07 07 07 07 07 07 07
DES的具体算法过程很复杂,实话说我也不懂,我只能借用Android和iOS里面自带的API去实现3DES的过程,其具体代码如下:
Android代码
public byte[] triDesEncrypt(byte[] desKey, byte[] desData, int flag) {//flag == 1为加密,flag == 0为解密 byte[] keyFirst8 = new byte[8]; byte[] keySecond8 = new byte[8]; if (desKey.length > 8) { for (int i = 0; i < 8; i++) { keyFirst8[i] = desKey[i]; } } else { return null; } if (desKey.length < 16) { for (int i = 0; i < desKey.length - 8; i++) { keySecond8[i] = desKey[i + 8]; } } else { for (int i = 0; i < 8; i++) { keySecond8[i] = desKey[i + 8]; } } byte[] tmpKey = new byte[8]; byte[] tmpData = new byte[8]; arrayCopy(keyFirst8, 0, tmpKey, 0, 8); arrayCopy(desData, 0, tmpData, 0, 8); int mode = flag; byte[] result = unitDes(tmpKey, tmpData, mode); arrayCopy(keySecond8, 0, tmpKey, 0, 8); arrayCopy(result, 0, tmpData, 0, 8); mode = (mode == 1) ? 0 : 1; result = unitDes(tmpKey, tmpData, mode); arrayCopy(keyFirst8, 0, tmpKey, 0, 8); arrayCopy(result, 0, tmpData, 0, 8); mode = (mode == 1) ? 0 : 1; result = unitDes(tmpKey, tmpData, mode); return result; }
iOS代码
+ (NSData *)encryptWithDataKey:(NSData *)src key1:(NSData *)key1 key2:(NSData *)key2 key3:(NSData *)key3 { if (src == nil || [src length] == 0 || key1 == nil || [key1 length] == 0 || key2 == nil || [key2 length] == 0 || key3 == nil || [key3 length] == 0) { return nil; } const void *vplainText; size_t plainTextBufferSize; plainTextBufferSize = [src length]; vplainText = [src bytes]; CCCryptorStatus ccStatus; uint8_t *bufferPtr = NULL; size_t bufferPtrSize = 0; size_t movedBytes = 0; bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1); bufferPtr = malloc(bufferPtrSize * sizeof(uint8_t)); memset((void *)bufferPtr, 0x00, bufferPtrSize); NSMutableData *key = [NSMutableData data]; [key appendData:key1]; [key appendData:key2]; [key appendData:key3]; NSString *initVec = @"01234567"; const void *vKey = [key bytes]; const void *vinitVec = (const void *)[initVec UTF8String]; uint8_t iv[kCCBlockSize3DES]; memset((void *)iv, 0x00, (size_t)sizeof(iv)); ccStatus = CCCrypt(kCCEncrypt, kCCAlgorithm3DES, kCCOptionPKCS7Padding | kCCOptionECBMode, vKey, kCCKeySize3DES, vinitVec, vplainText, plainTextBufferSize, (void *)bufferPtr, bufferPtrSize, &movedBytes); if (ccStatus != kCCSuccess) { free(bufferPtr); return nil; } NSData *result = [NSData dataWithBytes:bufferPtr length:movedBytes]; free(bufferPtr); return result; } + (NSData *)decryptWithDataKey:(NSData *)src key1:(NSData *)key1 key2:(NSData *)key2 key3:(NSData *)key3 { if (src == nil || [src length] == 0 || key1 == nil || [key1 length] == 0 || key2 == nil || [key2 length] == 0 || key3 == nil || [key3 length] == 0) { return nil; } const void *vplainText; size_t plainTextBufferSize; plainTextBufferSize = [src length]; vplainText = [src bytes]; CCCryptorStatus ccStatus; uint8_t *bufferPtr = NULL; size_t bufferPtrSize = 0; size_t movedBytes = 0; bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1); bufferPtr = malloc(bufferPtrSize * sizeof(uint8_t)); memset((void *)bufferPtr, 0x00, bufferPtrSize); NSMutableData *key = [NSMutableData data]; [key appendData:key1]; [key appendData:key2]; [key appendData:key3]; NSString *initVec = @"01234567"; const void *vkey = [key bytes]; const void *vinitVec = (const void *)[initVec UTF8String]; uint8_t iv[kCCBlockSize3DES]; memset((void *)iv, 0x00, (size_t)sizeof(iv)); ccStatus = CCCrypt(kCCDecrypt, kCCAlgorithm3DES, kCCOptionPKCS7Padding | kCCOptionECBMode, vkey, kCCKeySize3DES, vinitVec, vplainText, plainTextBufferSize, (void *)bufferPtr, bufferPtrSize, &movedBytes); if (ccStatus != kCCSuccess) { free(bufferPtr); return nil; } NSData *result = [NSData dataWithBytes:bufferPtr length:movedBytes]; free(bufferPtr); return result; }
相关文章推荐
- 用ASP编写的加密和解密类
- VBS脚本加密/解密VBS脚本(简易免杀版1.1)
- BAT加密工具 EncryBat 非编译型bat批处理加密方案与代码
- C#对称加密(AES加密)每次生成的结果都不同的实现思路和代码实例
- SQLServer 2008中的代码安全(一) 存储过程加密与安全上下文
- 实例讲解SQL Server加密功能
- C#实现对文件进行加密解密的方法
- C#实现数据包加密与解密实例详解
- C#最简单的字符串加密解密方法
- C#加密app.config中连接字符串的方法
- C#使用伪随机数实现加密用户密码的方法
- asp MD5加密方式使用建议
- C#对称加密与非对称加密实例
- 浅谈C#中Md5和Sha1两种加密方式
- 基于C#对用户密码使用MD5加密与解密
- vbs shellcode转换escape加密
- PHP加密解密字符串汇总
- PHP加密解密实例分析
- php结合md5实现的加密解密方法
- c#通过DES加密算法加密大文件的方法