AES加密,iOS刻恭、android、PHP 相互兼容

DEMO 綜述:

一行代碼完成AES加密季惯,加密模式 AES128 + ECB + NoPadding

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

DEMO GIF


DEMO 簡(jiǎn)介:

最近項(xiàng)目中用到AES加密吠各,在這里整理成篇,供大家參考閱讀勉抓,在使用該demo過程中贾漏,你可能會(huì)遇到一些問題,首先你需要看一下下面的demo簡(jiǎn)介藕筋,看看該demo 是否適合你的項(xiàng)目纵散。

項(xiàng)目中的AES加解密主要用在網(wǎng)絡(luò)請(qǐng)求過程中對(duì)上傳的參數(shù)進(jìn)行加密,對(duì)從后臺(tái)服務(wù)器獲取的數(shù)據(jù)進(jìn)行解密。

整體的加密流程為:

加密的過程: 參數(shù)字典 --> json字符串 --> base64加密后的字符串 --> AES加密后base64再加密 --> 輸出最終加密后的字符串;

解密的過程:

后臺(tái)服務(wù)器獲取加密的字符串 -->base64解密 --> AES解密后base64解密 --> json字符串 --> 數(shù)據(jù)字典;(與加密的過程相反)

網(wǎng)上對(duì)AES的詳細(xì)介紹已經(jīng)有很多伍掀,在這里不做贅述掰茶,如果你需要了解這些知識(shí),度娘蜜笤,google 去吧.

在這里感謝這些 blog 的作者,讓我在開發(fā)過程中少走了很多彎路:

http://www.open-open.com/lib/view/open1453530956573.html

http://blog.csdn.net/huangwenkui1990/article/details/48292865

http://blog.csdn.net/j_akill/article/details/44079597

https://wordpress-xiaominfc.rhcloud.com/?p=22#comment-12

http://www.360doc.com/content/15/1012/10/20918780_505049436.shtml

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

我們公司后臺(tái)為PHP,移動(dòng)端有iOS與Android, 討論后選擇AES的加密模式為 AES128 + ECB + NoPadding (注意是否滿足你的加密需求)濒蒋。

為什么選擇這種加密模式:

因?yàn)锳ES的加密規(guī)則 --> 原輸入數(shù)據(jù)不夠16字節(jié)的整數(shù)位時(shí),就要補(bǔ)齊把兔。因此就會(huì)有padding(填充模式)沪伙,若使用不同的padding,那么加密

出來的結(jié)果也會(huì)不一樣县好。

如果采用PKCS7Padding或者PKCS5Padding這種加密方式围橡,末端添加的數(shù)據(jù)可能不固定,在解碼后需要把末端多余的字符去掉缕贡,比較棘手翁授。

如果不管補(bǔ)齊多少位,末端都是'\0',去掉的話比較容易操作晾咪。 最主要的是能使得

iOS/Android/PHP相互通信收擦,也是加密過程中最難搞的地方,尤其需要開發(fā)者注意禀酱。

(注意:別的加密模式也可以完成三者之間的通信炬守,只是查找方法的時(shí)候 AES128 + ECB + NoPadding

這種加密方式使用的比較多,希望能有更好用的加密方式)

項(xiàng)目中用到了 google 的 base64 加解密庫 GTMBase64剂跟,但是這個(gè)庫已經(jīng)有很多年沒有更新 還是 MRC 開發(fā)模式,需要手動(dòng)配置一下:

1.選擇項(xiàng)目中的Targets酣藻,選中你所要操作的Target曹洽,

2.選Build Phases,在其中Complie Sources中選擇需要ARC的文件雙擊辽剧,并在輸入框中輸入 -fno-objc-arc

DEMO 中工具類的介紹:

.h文件

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

函數(shù)名稱 : + (NSString *)inputDictionary:(NSMutableDictionary *)dict andSecretKey:(NSString *)key;

函數(shù)描述 : 將傳進(jìn)來的字典 進(jìn)行 AES 加密后轉(zhuǎn)成json字符串

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

輸入?yún)?shù) : base64String? base64編碼的字符串 ; key? 密鑰

返回參數(shù) :? (NSDictionary *)dic? 字典

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

*/

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

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

函數(shù)名稱 : + (NSDictionary *)inputBase64String:(NSString *)base64String andSecretKey:(NSString *)key;

函數(shù)描述 : 將傳進(jìn)來的base64編碼的字符 進(jìn)行 AES 解密后轉(zhuǎn)成字典

解密的過程 : 與加密過程相反

輸入?yún)?shù) : base64String? base64編碼的字符串 ; key? 密鑰

返回參數(shù) :? (NSDictionary *)dic? 字典

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

*/

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

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

函數(shù)名稱 : + (NSString*)dictionaryToJson:(NSDictionary *)dic;

函數(shù)描述 : 將字典轉(zhuǎn)換成字符串

輸入?yún)?shù) : (NSDictionary *)dic? 字典

返回參數(shù) : 字符串

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

*/

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

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

函數(shù)名稱 : + (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString;

函數(shù)描述 : 將json字符串轉(zhuǎn)換成字典

輸入?yún)?shù) : (NSString *)jsonString? Json格式的字符串

返回參數(shù) : 字典

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

*/

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


.m文件

+ (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;

}

/**

*? AES 加密 解密

*/

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

{

char keyPtr[kCCKeySizeAES128+1];

memset(keyPtr, 0, sizeof(keyPtr));

[secretKeys getCString:keyPtr maxLength:sizeof(keyPtr) 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,//這個(gè)參數(shù)iv是個(gè)固定值偷崩,通常直接使用密鑰即可。大家一定要注視這個(gè)參數(shù)撞羽,如果安卓阐斜、服務(wù)端和iOS端不統(tǒng)一,那么加密結(jié)果就會(huì)不一樣诀紊,解密可能能解出來谒出,但是解密后在末尾會(huì)出現(xiàn)一些\0、\t之類的。(注: 這里使用NULL)

dataPtr,

sizeof(dataPtr),

buffer,

bufferSize,

&numBytesCrypted);

if (cryptStatus == kCCSuccess) {

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

return [GTMBase64 encodeBase64Data:resultData];

}

free(buffer);

return nil;

}


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

{

char keyPtr[kCCKeySizeAES128 + 1];

memset(keyPtr, 0, sizeof(keyPtr));

[secretKeys getCString:keyPtr maxLength:sizeof(keyPtr) 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,//這個(gè)參數(shù)iv是個(gè)固定值杀狡,通常直接使用密鑰即可蒙畴。大家一定要注視這個(gè)參數(shù),如果安卓呜象、服務(wù)端和iOS端不統(tǒng)一忍抽,那么加密結(jié)果就會(huì)不一樣,解密可能能解出來董朝,但是解密后在末尾會(huì)出現(xiàn)一些\0鸠项、\t之類的。(注:這里使用NULL)

[data bytes],

dataLength,

buffer,

bufferSize,

&numBytesCrypted);

if (cryptStatus == kCCSuccess) {

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

return [GTMBase64 decodeBase64Data:resultData];

}

free(buffer);

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(err) {

NSLog(@"json解析失斪咏:%@",err);

return nil;

}

return dic;

}


DEMO 使用示例

//加密

-(IBAction)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;

}

//解密

-(IBAction)clickDecodeBtn:(UIButton *)sender {

//上面加密的結(jié)果 NSString *AESString = @"yNgE5k1LAo7jfWk4oLqQv5YHxhBSOG0g6SjdFJoatZ2oTDL+jv1TpL7KWVcbMTH85kQCEFX9KWbsgegrwZ3JgrQ99I70Fd

LKjSieKe7rfTz1qmbL9gBoe8GJz3TeqmIs7252agKLSDofW8J3mK8y1F4Y3tdnMGsWO9DZLhS/1v0=";

//解密

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

NSString *jsonString = [CCPAESTool dictionaryToJson:dict];

self.showLabel.text = jsonString;

}

項(xiàng)目中遇到的一些坑祟绊,在 DEMO 中都已經(jīng)注釋出來,寫的比較清楚哥捕,如果該 DEMO 幫助了您牧抽,也希望能

給個(gè) star鼓勵(lì)一下,如果在使用中您有任何問題遥赚,可以在 github issues,我會(huì)盡自己能力給您答復(fù) 扬舒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市凫佛,隨后出現(xiàn)的幾起案子讲坎,更是在濱河造成了極大的恐慌,老刑警劉巖愧薛,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晨炕,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡毫炉,警方通過查閱死者的電腦和手機(jī)瓮栗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瞄勾,“玉大人费奸,你說我怎么就攤上這事〗福” “怎么了愿阐?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)四濒。 經(jīng)常有香客問我换况,道長(zhǎng)职辨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任戈二,我火速辦了婚禮舒裤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘觉吭。我一直安慰自己腾供,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布鲜滩。 她就那樣靜靜地躺著伴鳖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪徙硅。 梳的紋絲不亂的頭發(fā)上榜聂,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音嗓蘑,去河邊找鬼须肆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛桩皿,可吹牛的內(nèi)容都是我干的豌汇。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼泄隔,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼拒贱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起佛嬉,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤逻澳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后巷燥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赡盘,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年缰揪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片葱淳。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡钝腺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赞厕,到底是詐尸還是另有隱情艳狐,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布皿桑,位于F島的核電站毫目,受9級(jí)特大地震影響蔬啡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜镀虐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一箱蟆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刮便,春花似錦空猜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至搜贤,卻和暖如春谆沃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仪芒。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國打工唁影, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人桌硫。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓夭咬,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親卓舵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掏湾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • /**ios常見的幾種加密方法: 普通的加密方法是講密碼進(jìn)行加密后保存到用戶偏好設(shè)置( [NSUserDefaul...
    彬至睢陽閱讀 2,932評(píng)論 0 7
  • 常見的加密算法 MD5 \ SHA \ DES \ 3DES \ RC2和RC4 \ RSA \ IDEA \ D...
    小小啄閱讀 3,120評(píng)論 0 9
  • 前言: 在我們開發(fā)中免不了和服務(wù)器做一些數(shù)據(jù)交互,在交互過程中走得都是http請(qǐng)求拇涤,這類請(qǐng)求不像https那樣的安...
    退役程序猿閱讀 4,614評(píng)論 2 6
  • 首先羅列一些知識(shí)點(diǎn): 1.加密算法通常分為對(duì)稱性加密算法和非對(duì)稱性加密算法:對(duì)于對(duì)稱性加密算法惩坑,信息接收雙方都需事...
    JonesCxy閱讀 1,386評(píng)論 2 4
  • 楚楚: 不知你有沒有看過那部韓國電影趾痘,名字叫《密愛》岸军,講的是一對(duì)已婚男女出軌的事艰赞。劇中的女主人公因?yàn)檎煞虻那槿苏疑?..
    煙花_閱讀 554評(píng)論 27 19