iOS常用加密方法:
iOS开发过程中,可能会遇到一些信息加密问题。这里提供一些可用的iOS加解密方法。
1 md5加密:最终会得到一个32位的字符串,不可逆;
2 AES128,AES256加解密
AES128/256加解密的性能和选择:http://blog.csdn.net/newizan/article/details/45461347
AES256比AES128加密多耗时40左右,但是经得起暴力破解,AES128据说已经无法抵抗暴力破解。
3 DES加解密
AES与DES加密比较:http://wenku.baidu.com/link?url=m8c8S5vVM29ji4kXaR7tu5gyuNMRa7ekURwY7i0DP-ibCHyUR2VOGRXeSmoWvDot9Bnuj9DB9m0ovXxbbck9jZKR15jKNw-xe_vvJFKO5UK
总之,AES算法汇聚了安全性、效率高、易实现性和灵活性等优点,是一种较DES更好的算法。经过对DES 算法和AES 算法的比较分析,我们可以得出结论, 后者的效率明显高于前者, 而且由于AES 算法的简洁性,使得它的实现更为容易。AES 作为新一代的数据加密标准, 其安全性也远远高于DES 算法。更为重要的是,AES 算法硬件实现的速度大约是软件实现的3倍, 这就给用硬件实现加密提供了很好的机会。
加解密类
此加解密类实现了AES128,AES256和DES三种加密方式,具体选择哪种加密方式可以到.m 文件CCCrypt方法中进行参数修改(第二个参数可能需要相应修改)。
NSData+AES128.h
import <Foundation/Foundation.h>
@interface NSData (AES128)
//加密,kev和iv最多16位
- (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv;
//解密
- (NSData *)AES128DecryptWithKey:(NSString *)key iv:(NSString *)iv;
@end
NSData+AES128.m
#import "NSData+AES128.h"
#import <CommonCrypto/CommonCrypto.h>
@implementation NSData (AES128)
- (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv
{
return [self AES128Operation:kCCEncrypt key:key iv:iv];
}
- (NSData *)AES128DecryptWithKey:(NSString *)key iv:(NSString *)iv
{
return [self AES128Operation:kCCDecrypt key:key iv:iv];
}
- (NSData *)AES128Operation:(CCOperation)operation key:(NSString *)key iv:(NSString *)iv
{
//一个char数组,kCCKeySizeAES128 = 16
char keyPtr[kCCKeySizeAES128 + 1];
//把数组全部设置为0,
memset(keyPtr, 0, sizeof(keyPtr));
//把NSString存放到字符数组里面,字符数组最多是16位
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
//创建一个字符数组,kCCBlockSizeAES128 = 16
char ivPtr[kCCBlockSizeAES128 + 1];
//把字符数组全部值为 0
memset(ivPtr, 0, sizeof(ivPtr));
//把NSString 放进字符数组里面,最多16位 17位的话,最后一个不晓得要不要存放"\0"
[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
//取出要加密的数据的长度
NSUInteger dataLength = [self length];
//把该长度加上 kCCBlockSizeAES128 = 16
size_t bufferSize = dataLength + kCCBlockSizeAES128;
//从内存中开辟一个bufferSize大小的空间,指针给buffer (void *) 任意类型
void * buffer = malloc(bufferSize);
//numBytesCrypted 接收加密解密后的数据的长度
size_t numBytesCrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(operation,
kCCAlgorithmAES128,//此参数可能由加密参数不同需要相应修改
kCCOptionPKCS7Padding,
keyPtr,
kCCBlockSizeAES128,
// kCCKeySizeAES256,
// kCCKeySize3DES,
ivPtr,
[self bytes],
dataLength,
buffer,
bufferSize,
&numBytesCrypted);
if (cryptStatus == kCCSuccess)
{
//注意,此时的buffer是一个局部变量
NSData * cryptData=[NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
//这里的buffer没有free哦
return cryptData;
}
//buffer是malloc出来的,要释放掉
free(buffer);
return nil;
}
一般情况下我们在客户端加密数据,在服务器端进行解密,所以我们需要把加密的二进制数据再转化成字符串进行传输(便于传输解析),服务器收到我们传过去的字符串后再转化成加密的二进制数据,再对解析的加密数据的数据解析成正常的数据。
客户端:
123456->正常二进制加密数据->转化成正常字符串如:#klhg@Lifn进行传输
服务器:#klhg@Lifn->转化成正常二进制加密数据->123456
二进制和字符串数据相互转化的类如下:
ZGYBase64Encode.h
#import <Foundation/Foundation.h>
@interface ZGYBase64Encode : NSObject
//nsdata转换成base64编码字符串
+(NSString *)base64StrFromData:(NSData *)data;
//把base64编码的字符串转换成nsdata
+(NSData *)dataFromBase64Str:(NSString *)base64Str;
@end
ZGYBase64Encode.m
#import "ZGYBase64Encode.h"
@implementation ZGYBase64Encode
+(NSString *)base64StrFromData:(NSData *)data{
return [self encode:(const uint8_t*) data.bytes length:data.length];
}
+(NSData *)dataFromBase64Str:(NSString *)base64Str{
return [self decode:[base64Str cStringUsingEncoding:NSASCIIStringEncoding] length:base64Str.length];
}
#pragma mark - 具体实现 -
//这是一个静态的char数组,
static char zgyDecodingTable[128];
#define ArrayLength(x) (sizeof(x)/sizeof(*(x)))
+ (void) initialize
{
//一串char数组,用来初始化efunDecodingTable
char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (self == [ZGYBase64Encode class])
{
//把char 数组清零
memset(zgyDecodingTable, 0, ArrayLength(zgyDecodingTable));
//利用 encodingTable,循环初始化,efunDecodingTable 数组的一部分char,值是xxx
for (NSInteger i = 0; i < ArrayLength(encodingTable); i++)
{
zgyDecodingTable[encodingTable[i]] = i;
}
}
}
+ (NSString*) encode:(const uint8_t*) input length:(NSInteger) length
{
char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// 声明一个可变的OC数据
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
//uint8_t 你会发现是一个unsign char;但是,这里还有一个*
uint8_t * output = (uint8_t*)data.mutableBytes;
//注意这个循环,每次跳跃仨
for (NSInteger i = 0; i < length; i += 3)
{
NSInteger value = 0;
for (NSInteger j = i; j < (i + 3); j++)
{
value <<= 8;
if (j < length)
{
value |= (0xFF & input[j]);
}
}
NSInteger index = (i / 3) * 4;
output[index + 0] = encodingTable[(value >> 18) & 0x3F];
output[index + 1] = encodingTable[(value >> 12) & 0x3F];
output[index + 2] = (i + 1) < length ? encodingTable[(value >> 6) & 0x3F] : '=';
output[index + 3] = (i + 2) < length ? encodingTable[(value >> 0) & 0x3F] : '=';
}
//他妈,之前没有autorelease,函数返回值,一定记得autorelease,内存不能坑爹有木有
return [[[NSString alloc] initWithData:data
encoding:NSASCIIStringEncoding]autorelease];
}
+ (NSData*) decode:(const char*) string length:(NSInteger) inputLength
{
//如果字符串为空,或者长度不是4的整数倍,直接返回空。
if ((string == NULL) || (inputLength % 4 != 0)) {
return nil;
}
//去掉字符串后面的所有“=”
while (inputLength > 0 && string[inputLength - 1] == '=') {
inputLength--;
}
NSInteger outputLength = inputLength * 3 / 4;
NSMutableData* data = [NSMutableData dataWithLength:outputLength];
uint8_t* output = data.mutableBytes;
NSInteger inputPoint = 0;
NSInteger outputPoint = 0;
while (inputPoint < inputLength)
{
char i0 = string[inputPoint++];
char i1 = string[inputPoint++];
char i2 = inputPoint < inputLength ? string[inputPoint++] : 'A';
char i3 = inputPoint < inputLength ? string[inputPoint++] : 'A';
output[outputPoint++] = (zgyDecodingTable[i0] << 2) | (zgyDecodingTable[i1] >> 4);
if (outputPoint < outputLength)
{
output[outputPoint++] = ((zgyDecodingTable[i1] & 0xf) << 4) | (zgyDecodingTable[i2] >> 2);
}
if (outputPoint < outputLength)
{
output[outputPoint++] = ((zgyDecodingTable[i2] & 0x3) << 6) | zgyDecodingTable[i3];
}
}
return data;
}
@end
使用示例
- (void)viewDidLoad {
[super viewDidLoad];
NSString *password = @"123456";
//字符串转换成nsdata
NSData *pData = [password dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@",pData);
//对pData进行加密得到加密后的nsdata
NSData *encryptData = [pData AES128EncryptWithKey:@"haha" iv:@"hehe"];
NSLog(@"%@",encryptData);
//把加密之后的nsdata进行64编码转换成字符串。解密未使用转化字符串,只是示例
NSString *encryptStr = [ZGYBase64Encode base64StrFromData:encryptData];
NSLog(@"%@",encryptStr);
NSData *thedata = [ZGYBase64Encode dataFromBase64Str:encryptStr];
NSLog(@"%@",thedata);
//对encryptData进行解密,得到解密后的nsdata
NSData *decryptData = [encryptData AES128DecryptWithKey:@"haha" iv:@"hehe"];
NSLog(@"%@",decryptData);
NSString *decryptStr = [[NSString alloc] initWithData:decryptData encoding:NSUTF8StringEncoding];
NSLog(@"%@",decryptStr);
}