相互兼容,IOS开发各种加解密

作者: 编程应用  发布:2019-09-14

DEMO 综述:

1.AES加解密,给NSData添加类别 NSData+AES

一行代码完成AES加密,加密模式 AES128 + ECB + NoPadding

添加头文件#import

DEMO下载地址:github.com/IMCCP/CCPAESEncode

- (NSData *)AES256EncryptWithKey:(NSString *)key {//加密

DEMO GIF

char keyPtr[kCCKeySizeAES256+1];

图片 1

bzero(keyPtr, sizeof(keyPtr));

DEMO 简介:

[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

最近项目中用到AES加密,在这里整理成篇,供大家参考阅读,在使用该demo过程中,你可能会遇到一些问题,首先你需要看一下下面的demo简介,看看该demo 是否适合你的项目。

NSUInteger dataLength = [self length];

项目中的AES加解密主要用在网络请求过程中对上传的参数进行加密,对从后台服务器获取的数据进行解密。

size_t bufferSize = dataLength + kCCBlockSizeAES128;

整体的加密流程为:

void *buffer = malloc(bufferSize);

加密的过程: 参数字典 --> json字符串 --> base64加密后的字符串 --> AES加密后base64再加密 --> 输出最终加密后的字符串;

size_t numBytesEncrypted = 0;

解密的过程:

CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,

后台服务器获取加密的字符串 -->base64解密 --> AES解密后base64解密 --> json字符串 --> 数据字典;

kCCOptionPKCS7Padding | kCCOptionECBMode,

网上对AES的详细介绍已经有很多,在这里不做赘述,如果你需要了解这些知识,度娘,google 去吧.

keyPtr, kCCBlockSizeAES128,

在这里感谢这些 blog 的作者,让我在开发过程中少走了很多弯路:

NULL,

[self bytes], dataLength,

buffer, bufferSize,

&numBytesEncrypted);

if (cryptStatus == kCCSuccess) {

return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];

tanqisen.github.io/blog/2014/06/06/how-to-prevent-app-crack/ (如何防止客户端被破解)

}

我们公司后台为PHP,移动端有iOS与Android, 讨论后选择AES的加密模式为 AES128

free(buffer);

  • ECB + NoPadding (注意是否满足你的加密需求)。

return nil;

为什么选择这种加密模式:

}

因为AES的加密规则 --> 原输入数据不够16字节的整数位时,就要补齐。因此就会有padding,若使用不同的padding,那么加密

- (NSData *)AES256DecryptWithKey:(NSString *)key {//解密

出来的结果也会不一样。

char keyPtr[kCCKeySizeAES256+1];

如果采用PKCS7Padding或者PKCS5Padding这种加密方式,末端添加的数据可能不固定,在解码后需要把末端多余的字符去掉,比较棘手。

bzero(keyPtr, sizeof(keyPtr));

如果不管补齐多少位,末端都是'',去掉的话比较容易操作。 最主要的是能使得

[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

iOS/Android/PHP相互通信,也是加密过程中最难搞的地方,尤其需要开发者注意。

NSUInteger dataLength = [self length];

(注意:别的加密模式也可以完成三者之间的通信,只是查找方法的时候 AES128

size_t bufferSize = dataLength + kCCBlockSizeAES128;

  • ECB + NoPadding

void *buffer = malloc(bufferSize);

这种加密方式使用的比较多,希望能有更好用的加密方式)

size_t numBytesDecrypted = 0;

项目中用到了 google 的 base64 加解密库 GTMBase64,但是这个库已经有很多年没有更新 还是 MRC 开发模式,需要手动配置一下:

CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,

1.选择项目中的Targets,选中你所要操作的Target,

kCCOptionPKCS7Padding | kCCOptionECBMode,

2.选Build Phases,在其中Complie Sources中选择需要ARC的文件双击,并在输入框中输入 -fno-objc-arc

keyPtr, kCCBlockSizeAES128,

DEMO 中工具类的介绍:

NULL,

.h文件

[self bytes], dataLength,

/************************************************************************

函数名称 : + (NSString *)inputDictionary:(NSMutableDictionary *)dict andSecretKey:(NSString *)key;

函数描述 : 将传进来的字典 进行 AES 加密后转成json字符串

加密的过程: 字典 --> json字符串 --> base64加密后的字符串 --> AES加密后base64再加密 --> 输出加密后的字符串

输入参数 : base64String base64编码的字符串 ; key 密钥

返回参数 : (NSDictionary *)dic 字典

**********************************************************************

*/

+ (NSString *)inputDictionary:(NSMutableDictionary *)dict andSecretKey:(NSString *)key;

/************************************************************************

函数名称 : + (NSDictionary *)inputBase64String:(NSString *)base64String andSecretKey:(NSString *)key;

函数描述 : 将传进来的base64编码的字符 进行 AES 解密后转成字典

解密的过程 : 与加密过程相反

输入参数 : base64String base64编码的字符串 ; key 密钥

返回参数 : (NSDictionary *)dic 字典

**********************************************************************

*/

+ (NSDictionary *)inputBase64String:(NSString *)base64String andSecretKey:(NSString *)key;

/************************************************************************

函数名称 : + (NSString*)dictionaryToJson:(NSDictionary *)dic;

函数描述 : 将字典转换成字符串

输入参数 : (NSDictionary *)dic 字典

返回参数 : 字符串

**********************************************************************

*/

+ (NSString*)dictionaryToJson:(NSDictionary *)dic;

/************************************************************************

函数名称 : + (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString;

函数描述 : 将json字符串转换成字典

输入参数 : (NSString *)jsonString Json格式的字符串

返回参数 : 字典

**********************************************************************

*/

+ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString;

buffer, bufferSize,

.m文件

&numBytesDecrypted);

+ (NSString *)inputDictionary:(NSMutableDictionary *)dict andSecretKey:(NSString *)key{

NSString *jsonString = [CCPAESTool dictionaryToJson:dict];

NSString *jsonBase64Str = [GTMBase64 encodeBase64String:jsonString];

NSString *encryptStr = [CCPAESTool AES128Encrypt:jsonBase64Str andSecretKey:key];

return encryptStr;

}

+ (NSDictionary *)inputBase64String:(NSString *)base64String andSecretKey:(NSString *)key {

NSString * jsonString = [CCPAESTool AES128Decrypt:base64String andSecretKey:key];

NSDictionary *dict = [CCPAESTool dictionaryWithJsonString:jsonString];

return dict;

}

if (cryptStatus == kCCSuccess) {

/**

return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];

* AES 加密 解密

}

*/

free(buffer);

+(NSString *)AES128Encrypt:(NSString *)plainText andSecretKey:(NSString *)secretKeys

{

char keyPtr[kCCKeySizeAES128+1];

memset(keyPtr, 0, sizeof;

[secretKeys getCString:keyPtr maxLength:sizeof encoding:NSUTF8StringEncoding];

NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];

NSUInteger dataLength = [data length];

NSUInteger diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);

NSUInteger newSize = 0;

if(diff > 0)

{

newSize = dataLength + diff;

}

char dataPtr[newSize];

memcpy(dataPtr, [data bytes], [data length]);

for(int i = 0; i < diff; i++)

{

dataPtr[i + dataLength] = 0x0000; ////No padding

}

size_t bufferSize = newSize + kCCBlockSizeAES128;

void *buffer = malloc(bufferSize);

memset(buffer, 0, bufferSize);

size_t numBytesCrypted = 0;

CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,

kCCAlgorithmAES128,

kCCOptionECBMode, //使用的是 kCCOptionECBMode ,也就是ECB。在安卓端和PHP端,也得使用ECB

keyPtr,

kCCKeySizeAES128,

NULL,//这个参数iv是个固定值,通常直接使用密钥即可。大家一定要注视这个参数,如果安卓、服务端和iOS端不统一,那么加密结果就会不一样,解密可能能解出来,但是解密后在末尾会出现一些、t之类的。(注: 这里使用NULL)

dataPtr,

sizeof,

buffer,

bufferSize,

&numBytesCrypted);

if (cryptStatus == kCCSuccess) {

NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];

return [GTMBase64 encodeBase64Data:resultData];

}

free;

return nil;

}

+ (NSString *)AES128Decrypt:(NSString *)encryptText andSecretKey:(NSString *)secretKeys

{

char keyPtr[kCCKeySizeAES128 + 1];

memset(keyPtr, 0, sizeof;

[secretKeys getCString:keyPtr maxLength:sizeof encoding:NSUTF8StringEncoding];

NSData *data = [GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]];

NSUInteger dataLength = [data length];

size_t bufferSize = dataLength + kCCBlockSizeAES128;

void *buffer = malloc(bufferSize);

size_t numBytesCrypted = 0;

CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,

kCCAlgorithmAES128,

kCCOptionECBMode,//使用的是 kCCOptionECBMode ,也就是ECB。在安卓端和PHP端,也得使用ECB

keyPtr,

kCCBlockSizeAES128,

NULL,//这个参数iv是个固定值,通常直接使用密钥即可。大家一定要注视这个参数,如果安卓、服务端和iOS端不统一,那么加密结果就会不一样,解密可能能解出来,但是解密后在末尾会出现一些、t之类的。(注:这里使用NULL)

[data bytes],

dataLength,

buffer,

bufferSize,

&numBytesCrypted);

if (cryptStatus == kCCSuccess) {

NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];

return [GTMBase64 decodeBase64Data:resultData];

}

free;

return nil;

}

+ (NSString*)dictionaryToJson:(NSMutableDictionary *)dic {

NSError *parseError = nil;

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&parseError];

return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

}

+ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString {

if (jsonString == nil) {

return nil;

}

NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];

NSError *err;

NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];

if {

NSLog(@"json解析失败:%@",err);

return nil;

}

return dic;

}

return nil;

DEMO 使用示例

}

//加密

2.base64编解码参考

-clickEncodeBtn:(UIButton *)sender {

NSMutableDictionary *dict = [NSMutableDictionary dictionary];

dict[@"HELLO"] = @"WORLD";

dict[@"GIT"] = @"HUB";

dict[@"https"] = @"github.com/IMCCP";

NSString *AESString = [CCPAESTool inputDictionary:self.dict andSecretKey:secrectKey];

self.showLabel.text = AESString;

}

GTMDefines.h

//解密

GTMBase64.h

-clickDecodeBtn:(UIButton *)sender {

//上面加密的结果 NSString *AESString = @"yNgE5k1LAo7jfWk4oLqQv5YHxhBSOG0g6SjdFJoatZ2oTDL+jv1TpL7KWVcbMTH85kQCEFX9KWbsgegrwZ3JgrQ99I70Fd

LKjSieKe7rfTz1qmbL9gBoe8GJz3TeqmIs7252agKLSDofW8J3mK8y1F4Y3tdnMGsWO9DZLhS/1v0=";

//解密

NSDictionary *dict = [CCPAESTool inputBase64String:AESString andSecretKey:secrectKey];

NSString *jsonString = [CCPAESTool dictionaryToJson:dict];

self.showLabel.text = jsonString;

}

GTMBase64.m

项目中遇到的一些坑,在 DEMO 中都已经注释出来,写的比较清楚,如果该 DEMO 帮助了您,也希望能

3.各种加密,数字摘要。给NSString添加类别NSString+Encrypto

给个 star鼓励一下,如果在使用中您有任何问题,可以在 github issues,我会尽自己能力给您答复 。

(1).MD5数字摘要

- (NSString *)md5 {

const char *cStr = [self UTF8String];

unsigned char result[16];

CC_MD5( cStr, strlen(cStr), result );

return [NSString stringWithFormat:@%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X,

result[0], result[1], result[2], result[3],

result[4], result[5], result[6], result[7],

result[8], result[9], result[10], result[11],

result[12], result[13], result[14], result[15]

];

}

(2)SHA1摘要

- (NSString*) sha1

{

const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];

NSData *data = [NSData dataWithBytes:cstr length:self.length];

uint8_t digest[CC_SHA1_DIGEST_LENGTH];

CC_SHA1(data.bytes, data.length, digest);

NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];

for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)

[output appendFormat:@%02x, digest[i]];

return output;

}

(3)base64编码

- (NSString *) base64

{

NSData * data = [self dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

data = [GTMBase64 encodeData:data];

NSString * output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

return output;

}

(4)SHA1与base64结合

- (NSString *) sha1_base64

{

const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];

NSData *data = [NSData dataWithBytes:cstr length:self.length];

uint8_t digest[CC_SHA1_DIGEST_LENGTH];

CC_SHA1(data.bytes, data.length, digest);

NSData * base64 = [[NSData alloc]initWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];

base64 = [GTMBase64 encodeData:base64];

NSString * output = [[NSString alloc] initWithData:base64 encoding:NSUTF8StringEncoding];

return output;

}

(5)MD5与base64结合

- (NSString *) md5_base64

{

const char *cStr = [self UTF8String];

unsigned char digest[CC_MD5_DIGEST_LENGTH];

CC_MD5( cStr, strlen(cStr), digest );

NSData * base64 = [[NSData alloc]initWithBytes:digest length:CC_MD5_DIGEST_LENGTH];

base64 = [GTMBase64 encodeData:base64];

NSString * output = [[NSString alloc] initWithData:base64 encoding:NSUTF8StringEncoding];

return output;

}

4.3DES是一种对称的加密方式,因为用的同一个密钥。

对于加解密的安全性什么大家可以google,baidu自己找资料参考。

我也不过是简单的说一下通信加密中的一种可实现方案而已。

同样的3DES加密基本也都是统一的,系统也直接提供了API,基本代码如下

//3des加解密

+ (NSString*)TripleDES:(NSString*)plainText encryptOrDecrypt:(CCOperation)encryptOrDecrypt

{

const void *vplainText;

size_t plainTextBufferSize;

if (encryptOrDecrypt == kCCDecrypt)//解密

{

NSData *EncryptData = [GTMBase64 decodeData:[plainText dataUsingEncoding:NSUTF8StringEncoding]];

plainTextBufferSize = [EncryptData length];

vplainText = [EncryptData bytes];

}

else //加密

{

NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];

plainTextBufferSize = [data length];

vplainText = (const void *)[data 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, 0x0, bufferPtrSize);

// memset((void *) iv, 0x0, (size_t) sizeof(iv));

const void *vkey = (const void *) [DESKEY UTF8String];

// NSString *initVec = @init Vec;

//const void *vinitVec = (const void *) [initVec UTF8String];

// Byte iv[] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF};

ccStatus = CCCrypt(encryptOrDecrypt,

kCCAlgorithm3DES,

kCCOptionPKCS7Padding | kCCOptionECBMode,

vkey,

kCCKeySize3DES,

nil,

vplainText,

plainTextBufferSize,

(void *)bufferPtr,

bufferPtrSize,

&movedBytes);

//if (ccStatus == kCCSuccess) NSLog(@SUCCESS);

/*else if (ccStatus == kCC ParamError) return @PARAM ERROR;

else if (ccStatus == kCCBufferTooSmall) return @BUFFER TOO SMALL;

else if (ccStatus == kCCMemoryFailure) return @MEMORY FAILURE;

else if (ccStatus == kCCAlignmentError) return @ALIGNMENT;

else if (ccStatus == kCCDecodeError) return @DECODE ERROR;

else if (ccStatus == kCCUnimplemented) return @UNIMPLEMENTED; */

NSString *result;

if (encryptOrDecrypt == kCCDecrypt)

{

result = [[[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr

length:(NSUInteger)movedBytes]

encoding:NSUTF8StringEncoding]

autorelease];

}

else

{

NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];

result = [GTMBase64 stringByEncodingData:myData];

}

return result;

}

本文由今晚开什么码发布于编程应用,转载请注明出处:相互兼容,IOS开发各种加解密

关键词:

上一篇:iOS开辟之观望者形式初探
下一篇:没有了