iOS加密(一):Base64 +AES +MD5模式

由于公司對(duì)于信息安全比較注重,需要對(duì)json數(shù)據(jù)并用AES加密,然后生成url_safe base64編碼。然后繼續(xù)拼接時(shí)間戳 session還有其他字段進(jìn)行MD5加密。然后使用RAC簽名后傳輸。本來沒覺得什么,以為加密算法之前也接觸過,或者去網(wǎng)上直接套用就好柬祠,結(jié)果廓块,發(fā)現(xiàn)沒那么簡單 = =

一: Base64

  • 是網(wǎng)絡(luò)上使用最廣泛的編碼系統(tǒng),能夠?qū)⑷魏味M(jìn)制數(shù)據(jù),轉(zhuǎn)換成只有 65 個(gè)字符 * 組成的文本文件.
  • 編碼后的數(shù)據(jù)由 a-z A-Z 0-9 + / = 表示.
  • base64 編碼后的結(jié)果能夠反算,不夠安全.
  • base64 是所有現(xiàn)代加密算法的基礎(chǔ)算法.

base64可以用來將binary的字節(jié)序列數(shù)據(jù)編碼成ASCII字符序列構(gòu)成的文本,使用時(shí)亏钩,在傳輸編碼方式中指定base64。使用的字符包括大小寫字母各26個(gè)欺旧,加上10個(gè)數(shù)字姑丑,和加號(hào)“+”,斜杠“/”辞友,一共64個(gè)字符栅哀,等號(hào)“=”用來作為后綴用途。

完整的base64定義可見RFC 1421和RFC 2045称龙。編碼后的數(shù)據(jù)比原始數(shù)據(jù)略長留拾,為原來的4/3.。在電子郵件中鲫尊,根據(jù)RFC 822規(guī)定痴柔,每76個(gè)字符,還需要加上一個(gè)回車換行疫向】任担可以估算編碼后數(shù)據(jù)長度大約為原長的135.1%。( 如果源碼為760個(gè)字符, 則編碼后的長度為760 * (4 / 3) + 10(換行符) )

對(duì)Man進(jìn)行編碼
ABC編碼

URL_Safe Base64 這個(gè)參數(shù)意思是加密時(shí)不使用對(duì)URL和文件名有特殊意義的字符來作為加密字符,因?yàn)闃?biāo)準(zhǔn)base64包含"+"和"/",因此不適合直接放在URL中傳輸.因?yàn)閁RL編譯器會(huì)將"+","/"轉(zhuǎn)換成XX%的樣式.而這些"%"在錄入數(shù)據(jù)庫的時(shí)候還會(huì)進(jìn)行轉(zhuǎn)碼,為了解決此問題可采用一種適用于URL的改進(jìn)base64,它不在末位添加"=",將"+"轉(zhuǎn)換成"-",將"/"轉(zhuǎn)換成"_".

iOS原生API的有它自己的局限性, 所以我使用了base64的神器(GTMBase, 這個(gè)框架滿足了每一種的base64模式的編解碼.)
因此為了兩個(gè)平臺(tái)的兼容,使用總結(jié)如下

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
GTMBase64對(duì)應(yīng)的URL_Safe Base64

GTMBase64傳送門

二:AES加解密

  • 相較于DES和3DES算法而言搔驼,AES算法有著更高的速度和資源使用效率谈火,安全級(jí)別也較之更高了,被稱為下一代加密標(biāo)準(zhǔn)舌涨。
  • AES使用的是對(duì)稱加密.所謂對(duì)稱加密就是加解密雙方使用的密鑰相同.因此通過一種保密的方法讓客戶端與服務(wù)器擁有該密鑰,即可成功使用加解密.

常見的IOS中AES加密

//加密
+(NSData *) AES128EncryptWithKey:(NSData*)key data:(NSData*)data
{
    return [self doCipher:data iv:nil key:key context:kCCEncrypt error:nil];
}

//解密
+(NSData *) AES128DecryptWithKey:(NSData*)key data:(NSData*)data
{
    return [self doCipher:data iv:nil key:key context:kCCDecrypt error:nil];
}


+ (NSData *)doCipher:(NSData *)dataIn
                  iv:(NSData *)iv
                 key:(NSData *)symmetricKey
             context:(CCOperation)encryptOrDecrypt
               error:(NSError **)error
{
    CCCryptorStatus ccStatus   = kCCSuccess;
    size_t          cryptBytes = 0;
    NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];
    
    ccStatus = CCCrypt( encryptOrDecrypt,
                       kCCAlgorithmAES,
                       kCCOptionECBMode | kCCOptionPKCS7Padding,
                       symmetricKey.bytes,
                       symmetricKey.length,
                       iv.bytes,
                       dataIn.bytes,
                       dataIn.length,
                       dataOut.mutableBytes,
                       dataOut.length,
                       &cryptBytes);
    
    if (ccStatus == kCCSuccess) {
        dataOut.length = cryptBytes;
    }
    else {
        if (error) {
            *error = [NSError errorWithDomain:@"kEncryptionError"
                                         code:ccStatus
                                     userInfo:nil];
        }
        dataOut = nil;
    }
    
    return dataOut;
}

坑爹的地方地方來了,傳給后臺(tái)永遠(yuǎn)是亂碼.用了網(wǎng)上大多數(shù)方法都不行...一開始懷疑是不是URL_Safe Base64錯(cuò)了,或者是哪個(gè)地方?jīng)]有UTF-8糯耍。與后臺(tái)的溝通,反復(fù)驗(yàn)證數(shù)據(jù)加密后的字符串,就是對(duì)不上~~~

  • 網(wǎng)上拼命查資料發(fā)現(xiàn)好像是iv不對(duì),iv是什么??......
iOS原生API
  • 大概意思說,此屬性可選囊嘉,但只能用于CBC模式温技。如果出現(xiàn)那么他的長度必須和算法的block size保持一致。 如果是因?yàn)槟J(rèn)選擇的CBC模式而且向量沒有定義扭粱,那么向量會(huì)被定義為NULL荒揣。如果選擇了ECB模式或是其他的流密碼算法,之前所說的邏輯都不成立焊刹。

CBC??ECB一臉懵逼,繼續(xù)查資料

  • 初始化向量與密鑰相比有不同的安全性需求系任,因此IV通常無須保密,然而在大多數(shù)情況中虐块,不應(yīng)當(dāng)在使用同一密鑰的情況下兩次使用同一個(gè)IV俩滥。對(duì)于CBC和CFB,重用IV會(huì)導(dǎo)致泄露明文首個(gè)塊的某些信息贺奠,亦包括兩個(gè)不同消息中相同的前綴霜旧。對(duì)于OFB和CTR而言,重用IV會(huì)導(dǎo)致完全失去安全性儡率。另外挂据,在CBC模式中以清,IV在加密時(shí)必須是無法預(yù)測(cè)的;特別的崎逃,在許多實(shí)現(xiàn)中使用的產(chǎn)生IV的方法掷倔,例如SSL2.0使用的,即采用上一個(gè)消息的最后一塊密文作為下一個(gè)消息的IV个绍,是不安全的勒葱。
ECB模式不需要初始化向量,CBC需要巴柿。
CCCrypt重要參數(shù)

完善之后AES的代碼

//AES加密
+ (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv withNSData:(NSData *)data
{
    char keyPtr[kCCKeySizeAES128+1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    char ivPtr[kCCKeySizeAES128+1];
    bzero(ivPtr, sizeof(ivPtr));
    [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [data length];
    int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
    int newSize = 0;
    if(diff > 0)
    {
        newSize = (int)(dataLength + diff);
    }
    char dataPtr[newSize];
    memcpy(dataPtr, [data bytes], [data length]);
    for(int i = 0; i < diff; i++)
    {
        dataPtr[i + dataLength] = 0x00;
    }
    size_t bufferSize = newSize + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                          kCCAlgorithmAES128,
                                          0x00, //No padding
                                          keyPtr,
                                          kCCKeySizeAES128,
                                          ivPtr,
                                          dataPtr,
                                          sizeof(dataPtr),
                                          buffer,
                                          bufferSize,
                                          &numBytesEncrypted);
    if(cryptStatus == kCCSuccess)
    {
        //        NSData *data =[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
        //        NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }
    return nil;
}
//AES解密
+ (NSData *)AES128DecryptWithKey:(NSString *)key iv:(NSString *)iv withNSData:(NSData *)data
{
    char keyPtr[kCCKeySizeAES128+1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    char ivPtr[kCCKeySizeAES128+1];
    bzero(ivPtr, sizeof(ivPtr));
    [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [data length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                          kCCAlgorithmAES128,
                                          0x00, //No padding
                                          keyPtr,
                                          kCCKeySizeAES128,
                                          ivPtr,
                                          [data bytes],
                                          dataLength,
                                          buffer,
                                          bufferSize,
                                          &numBytesEncrypted);
    if(cryptStatus == kCCSuccess)
    {
        //        NSData *data =[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
        // NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }
    return nil;
}

寫個(gè)工具類復(fù)制過去就可以了

三:MD5

  • 對(duì)任意的數(shù)據(jù)進(jìn)行計(jì)算,生成固定長度的字符串.32個(gè)字符.
  • 一般用來加密密碼.
  • 有時(shí)候也用來驗(yàn)證文件下載時(shí),是否被篡改過.
    文件下載完成之后計(jì)算文件的md5值,與服務(wù)器計(jì)算的MD5值比較,如果不一樣那么這個(gè)文件在下載的過程中被篡改了.

MD5終端命令

# 得到文件的MD5值
$ md5 文件名

# 得到字符串的MD5值
md5 -s "string"
+(NSString *) md5: (NSString *) inPutText
{
    const char *cStr = [inPutText UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    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]
             ] lowercaseString];
}
  • 如果原始密碼過于簡單,直接進(jìn)行MD5加密是很容易被暴力破解的.
  • 為了增強(qiáng)密碼的安全性,防止加密的密碼被暴力破解,可以向原始密碼中加鹽.
  • 鹽 : 服務(wù)器端和客戶端約定的一個(gè)字符串.
  • MD5+鹽 : 原始密碼+鹽拼接出新的密碼字符串,再進(jìn)行MD加密.
  • 以上為加一勺鹽,比單純的直接MD5加密安全性要高.
  • 鹽要足夠的咸,越咸越安全.

RSA部分會(huì)在第二部分,如果有時(shí)間的話 笑~
參考文章:加密解密介紹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凛虽,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子广恢,更是在濱河造成了極大的恐慌凯旋,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钉迷,死亡現(xiàn)場(chǎng)離奇詭異瓦阐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)篷牌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來踏幻,“玉大人枷颊,你說我怎么就攤上這事「妹妫” “怎么了夭苗?”我有些...
    開封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長隔缀。 經(jīng)常有香客問我题造,道長,這世上最難降的妖魔是什么猾瘸? 我笑而不...
    開封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任界赔,我火速辦了婚禮,結(jié)果婚禮上牵触,老公的妹妹穿的比我還像新娘淮悼。我一直安慰自己,他們只是感情好揽思,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開白布袜腥。 她就那樣靜靜地躺著,像睡著了一般钉汗。 火紅的嫁衣襯著肌膚如雪羹令。 梳的紋絲不亂的頭發(fā)上鲤屡,一...
    開封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音福侈,去河邊找鬼酒来。 笑死,一個(gè)胖子當(dāng)著我的面吹牛癌刽,可吹牛的內(nèi)容都是我干的役首。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼显拜,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼衡奥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起远荠,我...
    開封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤矮固,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后譬淳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體档址,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年邻梆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了守伸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡浦妄,死狀恐怖尼摹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情剂娄,我是刑警寧澤蠢涝,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站阅懦,受9級(jí)特大地震影響和二,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜耳胎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一惯吕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧怕午,春花似錦混埠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春吏颖,著一層夾襖步出監(jiān)牢的瞬間搔体,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來泰國打工半醉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疚俱,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓缩多,卻偏偏與公主長得像呆奕,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子衬吆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

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