iOS与PHP/Android AES128 ECB NoPadding加密
来自: http://www.henishuo.com/ios-aes128-ecb-nopadding/
前言
谈谈AES加密,网上有很多的版本,当我没有真正在加密安全问题前,总以为百度出来某个AES加密算法就可以直接使用,实际上当我真正要做加密时,遇到了很多的坑,原来不是拿过来就能用的。写下本篇文章,记录下曾经遇到的坑,严防以后再出现同样的坑。
AES规则
原输入数据不够16字节的整数位时,就要补齐。因此就会有padding,若使用不同的padding,那么加密出来的结果也会不一样。
AES加密算法
苹果提供给我们的API只有这一个函数用来加密或者解密:
CCCryptorStatus CCCrypt( CCOperation op, /* kCCEncrypt, etc. */ CCAlgorithm alg, /* kCCAlgorithmAES128, etc. */ CCOptions options, /* kCCOptionPKCS7Padding, etc. */ const void *key, size_tkeyLength, const void *iv, /* optional initialization vector */ const void *dataIn, /* optional per op and alg */ size_tdataInLength, void *dataOut, /* data RETURNED here */ size_tdataOutAvailable, size_t*dataOutMoved) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
- 其中第一个 CCOperation 只有两个值,要么是 kCCEncrypt 表示加密,要么是 kCCDecrypt 表示解密。
- 第二个参数表示加密的算法,它只有以下向种类型:
enum { kCCAlgorithmAES128 = 0, kCCAlgorithmAES = 0, kCCAlgorithmDES, kCCAlgorithm3DES, kCCAlgorithmCAST, kCCAlgorithmRC4, kCCAlgorithmRC2, kCCAlgorithmBlowfish };typedef uint32_tCCAlgorithm;
我们这里使用的是 kCCAlgorithmAES128 表示使用AES128位加密。
- 第三个参数表示选项,这里使用的是 kCCOptionECBMode ,表示ECB:
enum { /* options for block ciphers */ kCCOptionPKCS7Padding = 0x0001, kCCOptionECBMode = 0x0002 /* stream ciphers currently have no options */};typedef uint32_tCCOptions;
- 第四个参数表示加密/解密的密钥。
- 第五个参数keyLength表示密钥的长度。
- 第六个参数iv是个固定值,通过直接使用密钥即可。大家一定要注视这个参数,如果安卓、服务端和iOS端不统一,那么加密结果就会不一样,解密可能能解出来,但是解密后在末尾会出现一些\0、\t之类的。
- 第七个参数dataIn表示要加密/解密的数据。
- 第八个参数dataInLength表示要加密/解密的数据的长度。
- 第九个参数dataOut用于接收加密后/解密后的结果。
- 第十个参数dataOutAvailable表示加密后/解密后的数据的长度。
- 第十一个参数dataOutMoved表示实际加密/解密的数据的长度。(因为有补齐)
加密算法
依赖于第三方库: GTMBase64 ,这个库已经几年没有维护了,现在还是MRC版本,要使用请到GITHUB查看使用教程,那里有ARC接入说明:
+ (NSString *)hyb_AESEncrypt:(NSString *)plainTextpassword:(NSString *)key { if (key == nil || (key.length != 16 && key.length != 32)) { return nil; } char keyPtr[kCCKeySizeAES128+1]; memset(keyPtr, 0, sizeof(keyPtr)); [keygetCString:keyPtrmaxLength:sizeof(keyPtr)encoding:NSUTF8StringEncoding]; char ivPtr[kCCBlockSizeAES128+1]; memset(ivPtr, 0, sizeof(ivPtr)); [keygetCString:ivPtrmaxLength:sizeof(ivPtr)encoding:NSUTF8StringEncoding]; NSData* data = [plainTextdataUsingEncoding:NSUTF8StringEncoding]; NSUInteger dataLength = [datalength]; int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128); unsigned long newSize = 0; if(diff > 0) { newSize = dataLength + diff; } char dataPtr[newSize]; memcpy(dataPtr, [databytes], [datalength]); for(int i = 0; i < diff; i++) { // 这里是关键,这里是使用NoPadding的 dataPtr[i + dataLength] = 0x0000; } size_tbufferSize = newSize + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); memset(buffer, 0, bufferSize); size_tnumBytesCrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode, [keyUTF8String], kCCKeySizeAES128, ivPtr, dataPtr, sizeof(dataPtr), buffer, bufferSize, &numBytesCrypted); if (cryptStatus == kCCSuccess) { NSData *resultData = [NSDatadataWithBytesNoCopy:bufferlength:numBytesCrypted]; return [GTMBase64stringByEncodingData:resultData]; } free(buffer); return nil;}
对于加密算法,大家一定要注意,保证iOS、安卓、服务端的加密规则是一定的,建议统一使用No Padding的,这里使用No Padding是这样的:
for(int i = 0; i < diff; i++) { // 这里是关键,这里是使用NoPadding的 dataPtr[i + dataLength] = 0x0000;}
其实所谓Padding就是指在位数不够需要补齐时,使用什么来填充,而No Padding就是使用16个0,对应0x0000.如果三端不统一,加密出来就算能解密,也会出现一些奇怪的字符,甚至会有部分乱码。
另外,这里使用的是 kCCOptionECBMode ,也就是ECB。在安卓端和PHP端,也得使用ECB。在调试过程中,发现PHP使用CBC解密不了IOS端的。于是改成了使用ECB。
解密算法
依赖于第三方库: GTMBase64 ,这个库已经几年没有维护了,现在还是MRC版本,要使用请到GITHUB查看使用教程,那里有ARC接入说明:
+ (NSString *)hyb_AESDecrypt:(NSString *)encryptTextpassword:(NSString *)key { if (key == nil || (key.length != 16 && key.length != 32)) { return nil; } char keyPtr[kCCKeySizeAES128 + 1]; memset(keyPtr, 0, sizeof(keyPtr)); [keygetCString:keyPtrmaxLength:sizeof(keyPtr)encoding:NSUTF8StringEncoding]; char ivPtr[kCCBlockSizeAES128 + 1]; memset(ivPtr, 0, sizeof(ivPtr)); [keygetCString:ivPtrmaxLength:sizeof(ivPtr)encoding:NSUTF8StringEncoding]; NSData *data = [GTMBase64decodeData:[encryptTextdataUsingEncoding:NSUTF8StringEncoding]]; NSUInteger dataLength = [datalength]; size_tbufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_tnumBytesCrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionECBMode, [keyUTF8String], kCCBlockSizeAES128, ivPtr, [databytes], dataLength, buffer, bufferSize, &numBytesCrypted); if (cryptStatus == kCCSuccess) { NSData *resultData = [NSDatadataWithBytesNoCopy:bufferlength:numBytesCrypted]; NSString *decoded=[[NSString alloc]initWithData:resultDataencoding:NSUTF8StringEncoding]; return decoded; } free(buffer); return nil;}
解密时也得跟加密一样指定为ECB,否则解出来会出现乱码,或者末尾会出现\0、\t之类的符号。
写在最后
开发中总会遇到各种坑,网上查了很多的资料,但是终究没有说明解决的办法,而是只将自己的代码放出来。对于刚接触这方面知识的开发人员来说,是很懵懂的。甚至很多新手会觉得系统就是这样的,我也没办法。其实总会有解决办法的,关键在于与其他各端统一连调。
关注我
Swift/ObjC技术群一:324400294(已满)
Swift/ObjC技术群二:494669518
ObjC/Swift高级群:461252383(注明年限,新手勿扰)
关注微信公众号: iOSDevShares
关注新浪微博账号:标哥Jacky
标哥的GITHUB地址: CoderJackyHuang
支持并捐助
如果您觉得文章对您很有帮忙,希望得到您的支持。您的捐肋将会给予我最大的鼓励,感谢您的支持!
支付宝捐助 | 微信捐助 |
---|---|

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。
