ios中的DES/CBC模式加密

来源:互联网 发布:搜狗输入法云计算候选 编辑:程序博客网 时间:2024/05/21 10:08

之前做一个IOS项目,是将公司已经做好的android项目转换成IOS项目。但是在处理DES加密时,加密后的字段一直不能匹配,这真心相当郁闷。只好稍微研究一下DES的加密模式。

首先现附上android端的加密代码:

public static final String ALGORITHM_DES = "DES/CBC/PKCS5Padding";private static String encode(String key, byte[] data) throws Exception {try {DESKeySpec dks = new DESKeySpec(key.getBytes());SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");Key secretKey = keyFactory.generateSecret(dks);Cipher cipher = Cipher.getInstance(ALGORITHM_DES);IvParameterSpec iv = new IvParameterSpec("12347890".getBytes());AlgorithmParameterSpec paramSpec = iv;cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);byte[] bytes = cipher.doFinal(data);return Base64.encodeToString(bytes, 0);} catch (Exception e) {throw new Exception(e);}}

首先要关注的是 ALGORITHM_DES = "DES/CBC/PKCS5Padding"; 这个变量。从中我们可以看出这是DES的CBC加密模式,用的是PKCS5Padding的填充模式。

之后代码使用ALGORITHM_DES来变量初始化Cipher

Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
在object-c中也有相对应的函数,代码如下:

CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES,                                          kCCOptionPKCS7Padding,                                          [key UTF8String], kCCKeySizeDES,                                          iv,                                          textBytes, dataLength,                                          buffer, 1024,                                          &numBytesEncrypted);
这里我们首先关注的是前面三个参数,第一个‘kCCEncrypt’ 是告诉函数执行加密过程,对应的也存在解密过程,具体的可以command+左键来查看详情;第二个kCCAlgorithmDES 便是告诉函数执行DES加密;第三个参数是 kCCOptionPKCS7Padding ,其实单单这个参数就是告诉了函数 运用CBC加密模式,并且使用PKCS7Padding的填充模式进行加密,这就有疑问了,这里根本就没看到CBC这个三个字母啊,怎么就是CBC加密模式了呢?

对第三个参数进行commend+左键查看,可以发现里面只有两个枚举变量,kCCOptionPKCS7Padding和kCCOptionECBMode。如果我们第三个变量写成kCCOptionPKCS7Padding|kCCOptionECBMode,就表示运用了ECB加密模式,并且使用PKCS7Padding的填充模式进行加密。所以单单使用kCCOptionPKCS7Padding就代表了CBC加密模式。至于为什么,and 其他加密模式怎么办等等,这个就只能呵呵了,真心不清楚!

之后就要说说,PKCS7Padding和PKCS5Padding的区别了,之前在做的时候一直以为是这个填充模式的区别导致的不匹配,所以一直想要寻找OC中PKCS5Padding填充模式的实现,但是没有,于是我崩溃了。崩溃过后,细心查询资料得知,在DES中加密数据包单位长度是8字节,在8字节的情况下PKCS7Padding 等价与 PKCS5Padding。貌似.net可以修改数据包长度,OC、Java不清楚能不能修改,但默认都是8字节的。因此手不要太轻,不随意修改默认值,就不用去纠结PKCS7Padding和PKCS5Padding了,要是你兴趣浓厚,那就随意。

那问题到底出在哪里!?其实是在IV向量上,IV是CBC模式的初始向量,至关重要。java中添加的IV向量如下

IvParameterSpec iv = new IvParameterSpec("12347890".getBytes());
而网上大部分代码iv是这样生成的

Byte iv[] = {1,2,3,4,5,6,7,8};
但是加密不匹配,具体原因可以查看CCCrypt函数第六个参数,它的类型是const void。之后用如下方式生成

const void *iv = (const void *)[key UTF8String];
然后密码匹配了,就这样成功了,泪奔。具体OC代码如下:

//DES加密+ (NSString *) encryptUseDES:(NSString *)plainText key:(NSString *)key{    NSString *ciphertext = nil;    const char *textBytes = [plainText UTF8String];    NSUInteger dataLength = [plainText length];    unsigned char buffer[1024];    memset(buffer, 0, sizeof(char));    const void *iv = (const void *)[key UTF8String];    size_t numBytesEncrypted = 0;    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES,                                          kCCOptionPKCS7Padding,                                          [key UTF8String], kCCKeySizeDES,                                          iv,                                          textBytes, dataLength,                                          buffer, 1024,                                          &numBytesEncrypted);    if (cryptStatus == kCCSuccess) {        NSData *data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesEncrypted];        ciphertext = [[NSString alloc] initWithData:[GTMBase64 encodeData:data] encoding:NSUTF8StringEncoding];    }    return ciphertext;}
头文件:

#import <CommonCrypto/CommonCryptor.h>#import "GTMBase64.h"

其中 GTMBase64.h 可以到此处下载

http://download.csdn.net/detail/u010184533/7849095

官方地址:

http://code.google.com/p/google-toolbox-for-mac/source/browse/trunk/Foundation/?r=87

0 0