iOS與Java后臺AES+Base64數據加解密(附demo)

本文從Base64的原理,Base64在iOS端和Java端不同的編解碼造成無法加解密的坑,AES的原理和一個完整的Demo.
希望看完本篇文章能讓讀者對客戶端與后臺的整體加密流程有更深的認識.因此本篇會寫的比較詳細.
Demo下載地址,歡迎大家的小星星

一: Base64原理

base64之所以稱為base64,是因為其用64個字符對任意數據進行編碼,標準base64的字符如下:


標準base64字符表

base64可以用來將binary的字節(jié)序列數據編碼成ASCII字符序列構成的文本,使用時赤炒,在傳輸編碼方式中指定base64。使用的字符包括大小寫字母各26個,加上10個數字,和加號“+”,斜杠“/”韧衣,一共64個字符,等號“=”用來作為后綴用途购桑。

完整的base64定義可見RFC 1421和RFC 2045畅铭。編碼后的數據比原始數據略長,為原來的4/3.勃蜘。在電子郵件中硕噩,根據RFC 822規(guī)定,每76個字符缭贡,還需要加上一個回車換行炉擅。可以估算編碼后數據長度大約為原長的135.1%阳惹。( 如果源碼為760個字符, 則編碼后的長度為760 * (4 / 3) + 10(換行符) )

對Man進行編碼
注意

當原數據長度不是3的整數倍時, 如果最后剩下一個輸入數據谍失,在編碼結果后加2個“=”;如果最后剩下兩個輸入數據莹汤,編碼結果后加1個“=”快鱼;如果沒有剩下任何數據,就什么都不要加,這樣才可以保證數據還原的正確性抹竹。

以 Hello!! 為例线罕,其轉換過程為:

對Hello!!進行編碼

Hello!! Base64編碼的結果為 SGVsbG8hIQAA 。最后2個零值只是為了Base64編碼而補充的窃判,在原始字符中并沒有對應的字符钞楼,那么Base64編碼結果中的最后兩個字符 AA 實際不帶有效信息,所以需要特殊處理袄琳,以免解碼錯誤询件。

標準Base64編碼通常用 = 字符來替換最后的 A,即編碼結果為 SGVsbG8hIQ==跨蟹。因為 = 字符并不在Base64編碼索引表中雳殊,其意義在于結束符號,在Base64解碼時遇到 = 時即可知道一個Base64編碼字符串結束窗轩。

根據上面的結論,可將base64分為如下的格式:

  • CRLF 這個參數看起來比較眼熟夯秃,它就是Win風格的換行符,意思就是使用CRLF這一對作為一行的結尾而不是Unix風格的LF
  • DEFAULT 這個參數是默認痢艺,使用默認的方法來加密
  • NO_PADDING 這個參數是略去加密字符串最后的”=”
  • NO_WRAP 這個參數意思是略去所有的換行符(設置后CRLF就沒用了,將每76個字符串產生的換行符略去)
  • URL_SAFE 這個參數意思是加密時不使用對URL和文件名有特殊意義的字符來作為加密字符,因為標準base64包含"+"和"/",因此不適合直接放在URL中傳輸.因為URL編譯器會將"+","/"轉換成XX%的樣式.而這些"%"在錄入數據庫的時候還會進行轉碼,為了解決此問題可采用一種適用于URL的改進base64,它不在末位添加"=",將"+"轉換成"-",將"/"轉換成"_".

iOS在7.0之后雖然可以用原生API進行base64編解碼

/* Create an NSData from a Base-64 encoded NSString using the given options. By default, returns nil when the input is not recognized as valid Base-64.
*/
- (nullable instancetype)initWithBase64EncodedString:(NSString *)base64String options:(NSDataBase64DecodingOptions)options NS_AVAILABLE(10_9, 7_0);

/* Create a Base-64 encoded NSString from the receiver's contents using the given options.
*/
- (NSString *)base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)options NS_AVAILABLE(10_9, 7_0);

/* Create an NSData from a Base-64, UTF-8 encoded NSData. By default, returns nil when the input is not recognized as valid Base-64.
*/
- (nullable instancetype)initWithBase64EncodedData:(NSData *)base64Data options:(NSDataBase64DecodingOptions)options NS_AVAILABLE(10_9, 7_0);

/* Create a Base-64, UTF-8 encoded NSData from the receiver's contents using the given options.
*/
- (NSData *)base64EncodedDataWithOptions:(NSDataBase64EncodingOptions)options NS_AVAILABLE(10_9, 7_0);

可是當你信心滿滿準備用原生API進行編解碼的時候,坑就來了

  • 坑一:由于測試的字段比較短,base64生成的結果完全一樣,你以為高枕無憂了.當字符串比較長的時候,NO_PADDING和有PADDING("="補位),生成的結果就完全不一樣咯.
  • 坑二:iOS這邊可能是使用的NO_WRAP加密的, Java后臺可以正常解密.可是反之就無法解出來.
  • 坑三:
    后臺返回的base64編碼字符串

    這是后臺返回的base64編碼字符串,根據上面我所寫的,這段字符串包含很多"-","_"字符串,說明后臺采用的base64模式為URL_SAFE.
    可是當時的我還傻乎乎的用蘋果原生API解碼這段字符串,可是解出的字符串永遠無法用AES秘鑰解密... ...

解決方法

其實解決方法真的就是一句話,跟你的后臺人員好好溝通 好好溝通 好好溝通, 加解密的每一個流程都要好好溝通!
iOS原生API的有它自己的局限性, 所以我使用了base64的神器(GTMBase, 小伙伴可以在我demo中下載這個框架,這個框架滿足了每一種的base64模式的編解碼.)
因此為了兩個平臺的兼容,使用總結如下

GTMBase64 Padded YES != Java DEFAULT
GTMBase64 Padded NO == Java NO_PADDING | NO_WRAP
GTMBase64 Padded YES == Java NO_WRAP
GTMBase64 websafe Padded NO == java NO_PADDING | NO_WRAP | URL_SAFE
GTMBase64 websafe Padded YES == java NO_WRAP | URL_SAFE

總結: 因此使用過程中要用長數據進行測試,不要因為只成功測試一段短數據就確定成功了.用一位前輩的話來說:前面人踩過的雷,后面的人就不要好奇了.

二:AES加解密

根據上文的血淚史,請問當你做到AES加密的時候你第一件事會干什么?
當然就是和后臺確定所用AES的密鑰長度!!! AES-256是永遠解不出AES-128加密的數據的.AES密鑰長度分為128,196,256三種長度.我在項目中使用的為128位.
AES使用的是對稱加密.所謂對稱加密就是加解密雙方使用的密鑰相同.因此通過一種保密的方法讓客戶端與服務器擁有該密鑰,即可成功使用加解密.

拿取AES密鑰的流程

  • 在客戶端生成RSA密鑰對,并將RSA公鑰傳給后臺,私鑰保存在客戶端(關于RSA的知識點會在下一章詳細介紹)
  • 后臺會將AES的密鑰通過RSA公鑰加密后傳送到客戶端,客戶端在本地通過RSA私鑰解密拿到AES密鑰.
  • 拿到AES密鑰后就可以與后臺完成加密數據傳輸了

使用AES傳輸數據的流程
(客戶端加密流程)

  • 將參數用AES密鑰加密
  • 將加密后的數據用base64編碼發(fā)送給后臺
    (客戶端解密流程)
  • 將后臺返回的數據用已經與后臺商量好的base64模式解碼
  • 講解碼后的數據用AES密鑰解密,就可以拿到后臺返回的json字符串,接下來轉模型轉字典都隨你.

整個與Java后臺交互的代碼就放在demo中了,希望能對大家有所幫助

總結:

1.無論那種加密方式,自己一個人是搞不出來的,所以與后臺的溝通很重要.
2.任何一種加解密方式都要在本地測試下,如果在本地都無法成功,那么就更別想與后臺交互了.

參考鏈接:http://devm.cn/2015/08/25/base64-java-ios.html
http://www.reibang.com/p/b8a5e1c770f9

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末仓洼,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子堤舒,更是在濱河造成了極大的恐慌色建,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舌缤,死亡現場離奇詭異箕戳,居然都是意外死亡,警方通過查閱死者的電腦和手機国撵,發(fā)現死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門陵吸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人介牙,你說我怎么就攤上這事壮虫。” “怎么了环础?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵囚似,是天一觀的道長。 經常有香客問我线得,道長饶唤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任贯钩,我火速辦了婚禮搬素,結果婚禮上呵晨,老公的妹妹穿的比我還像新娘。我一直安慰自己熬尺,他們只是感情好,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布谓罗。 她就那樣靜靜地躺著粱哼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪檩咱。 梳的紋絲不亂的頭發(fā)上揭措,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音刻蚯,去河邊找鬼绊含。 笑死,一個胖子當著我的面吹牛炊汹,可吹牛的內容都是我干的躬充。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼讨便,長吁一口氣:“原來是場噩夢啊……” “哼充甚!你這毒婦竟也來了?” 一聲冷哼從身側響起霸褒,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤伴找,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后废菱,有當地人在樹林里發(fā)現了一具尸體技矮,經...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年殊轴,在試婚紗的時候發(fā)現自己被綠了衰倦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡梳凛,死狀恐怖耿币,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情韧拒,我是刑警寧澤淹接,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站叛溢,受9級特大地震影響塑悼,放射性物質發(fā)生泄漏。R本人自食惡果不足惜楷掉,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一厢蒜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦斑鸦、人聲如沸愕贡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽固以。三九已至,卻和暖如春嘱巾,著一層夾襖步出監(jiān)牢的瞬間憨琳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工旬昭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留篙螟,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓问拘,卻偏偏與公主長得像遍略,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子场梆,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內容