iOS--加解密(對(duì)稱,非對(duì)稱)(AES DES base64這里都有),數(shù)字簽名,cookie

這篇文章不是研究性的東西,主要是簡(jiǎn)單的一些知識(shí), 開篇如此, 我盡量不讓讀者失望。

首先羅列一些知識(shí)點(diǎn):
1.加密算法通常分為對(duì)稱性加密算法和非對(duì)稱性加密算法:對(duì)于對(duì)稱性加密算法,信息接收雙方都需事先知道密匙和加解密算法且其密匙是相同的,之后便是對(duì)數(shù)據(jù)進(jìn)行 加解密了。非對(duì)稱算法與之不同,發(fā)送雙方A,B事先均生成一堆密匙,然后A將自己的公有密匙發(fā)送給B,B將自己的公有密匙發(fā)送給A,如果A要給B發(fā)送消息,則先需要用B的公有密匙進(jìn)行消息加密,然后發(fā)送給B端,此時(shí)B端再用自己的私有密匙進(jìn)行消息解密,B向A發(fā)送消息時(shí)為同樣的道理。

2.關(guān)于公鑰私鑰和數(shù)字簽名, 通過一個(gè)發(fā)送郵件的故事讓大家有一個(gè)深刻的理解,非常棒的案例:
http://www.blogjava.net/yxhxj2006/archive/2012/10/15/389547.html
看完這個(gè)之后, 相信你會(huì)明白非對(duì)稱加密在網(wǎng)絡(luò)傳輸中的安全性的體現(xiàn), 當(dāng)然就是之前談到的https。
總而言之:公鑰與私鑰的作用是:用公鑰加密的內(nèi)容只能用私鑰解密,用私鑰加密的內(nèi)容只能 用公鑰解密。<b>公鑰加密私鑰解密, 沒問題,也可以說是"公共密鑰加密系統(tǒng)"私鑰加密公鑰解密,一般不這么說,應(yīng)叫"私鑰簽名,公鑰驗(yàn)證",也可以說是“公共密鑰簽名系統(tǒng)”</b>
引用一段總結(jié)的話:
<b>
公鑰加密私鑰解密, 沒問題,也可以說是"公共密鑰加密系統(tǒng)"私鑰加密公鑰解密,一般不這么說,應(yīng)叫"私鑰簽名,公鑰驗(yàn)證",也可以說是“公共密鑰簽名系統(tǒng)”再來說一下"公共密鑰簽名系統(tǒng)"目的:(如果暈就多看幾遍,這個(gè)沒搞清,后面的代碼就更暈)A欲傳(信息)給B,但又怕B不確信該信息是A發(fā)的。1.A選計(jì)算(信息)的HASH值,如用MD5方式計(jì)算,得到:[MD5(信息)]2.然后用自已的私鑰加密HASH值,得到:[私鑰(MD5(信息))]3.最后將信息與密文一起傳給B:傳給B:[(信息) + 私鑰(MD5(信息))]B接到 :[(信息) + 私鑰(MD5(信息))]1.先用相同的HASH算法算出(信息)的HASH值,這里也使用MD5方式 得到: [MD5(信息)!]2. 再用A的公鑰解密 [ 私鑰(MD5(信息))] [公鑰(私鑰(MD5(信息)))] = [(MD5(信息)] 如能解開,證明該 [ 私鑰(MD5(信息))]是A發(fā)送的3.再比效[MD5(信息)!]與[(MD5(信息)] 如果相同,表示(信息)在傳遞過程中沒有被他人修改過
</b>

OK, 到現(xiàn)在為止, 你已經(jīng)懂得了公鑰, 私鑰, 以及數(shù)字證書的概念了, 當(dāng)然你也知道什么是對(duì)稱加密和非對(duì)稱加密,有可能你不是很清楚,為了讓你更清楚,給你再講個(gè)活生生的例子,這個(gè)例子還要從我的戀愛說起, 高中的時(shí)候喜歡上一個(gè)女生, 那時(shí)候青春年少,還喜歡用紙質(zhì)給她寫情書, 每天寫一些“透明的”文字很繁瑣,于是有一天,我忽然一個(gè)念想,把情書改成用漢語拼音寫abcd……xyz, 原來字母是a就用z代替,b用y代替,c用x代替,……z用a代替, 這樣,一個(gè)只有我們倆能看的懂的情書就這樣誕生了。其實(shí)現(xiàn)在想想, 這不正是一種對(duì)稱式加密么。哈哈。

說完了故事,再來普及下一點(diǎn)簡(jiǎn)單的知識(shí)嘍

3幾種對(duì)稱性加密算法:AES,DES,3DES

DES是一種分組數(shù)據(jù)加密技術(shù)(先將數(shù)據(jù)分成固定長(zhǎng)度的小數(shù)據(jù)塊,之后進(jìn)行加密),速度較快,適用于大量數(shù)據(jù)加密,而3DES是一種基于DES的加密算法,使用3個(gè)不同密匙對(duì)同一個(gè)分組數(shù)據(jù)塊進(jìn)行3次加密,如此以使得密文強(qiáng)度更高。
相較于DES和3DES算法而言,AES算法有著更高的速度和資源使用效率,安全級(jí)別也較之更高了,被稱為下一代加密標(biāo)準(zhǔn)。對(duì)于具體的算法我們不做深入的了解, 之前有一篇文章寫得很好, 由于時(shí)間問題, 我就不給大家找了。

4幾種非對(duì)稱性加密算法:RSA,DSA,ECC

RSA和DSA的安全性及其它各方面性能都差不多,而ECC較之則有著很多的性能優(yōu)越,包括處理速度,帶寬要求,存儲(chǔ)空間等等

5幾種線性散列算法(簽名算法):MD5,SHA1,HMAC

這幾種算法只生成一串不可逆的密文,經(jīng)常用其效驗(yàn)數(shù)據(jù)傳輸過程中是否經(jīng)過修改,因?yàn)橄嗤纳伤惴▽?duì)于同一明文只會(huì)生成唯一的密文,若相同算法生成的密文不同,則證明傳輸數(shù)據(jù)進(jìn)行過了修改。通常在數(shù)據(jù)傳說過程前,使用MD5和SHA1算法均需要發(fā)送和接收數(shù)據(jù)雙方在數(shù)據(jù)傳送之前就知道密匙生成算法,而HMAC與之不同的是需要生成一個(gè)密匙,發(fā)送方用此密匙對(duì)數(shù)據(jù)進(jìn)行摘要處理(生成密文),接收方再利用此密匙對(duì)接收到的數(shù)據(jù)進(jìn)行摘要處理,再判斷生成的密文是否相同。

6對(duì)于各種加密算法的選用

由于對(duì)稱加密算法的密鑰管理是一個(gè)復(fù)雜的過程,密鑰的管理直接決定著他的安全性,因此當(dāng)數(shù)據(jù)量很小時(shí),我們可以考慮采用非對(duì)稱加密算法。
在實(shí)際的操作過程中<b><b><b><b>我們通常采用的方式是:采用非對(duì)稱加密算法管理對(duì)稱算法的密鑰,然后用對(duì)稱加密算法加密數(shù)據(jù),這樣我們就集成了兩類加密算法的優(yōu)點(diǎn),既實(shí)現(xiàn)了加密速度快的優(yōu)點(diǎn),又實(shí)現(xiàn)了安全方便管理密鑰的優(yōu)點(diǎn)。</b></b></b></b>如果在選定了加密算法后,那采用多少位的密鑰呢?一般來說,密鑰越長(zhǎng),運(yùn)行的速度就越慢,應(yīng)該根據(jù)的我們實(shí)際需要的安全級(jí)別來選擇,一般來說,RSA建議采用1024位的數(shù)字,ECC建議采用160位,AES采用128為即可。

需要注意的是:

哈希函數(shù),比如MD5,SHA,這些都不是加密算法。要注意他們的區(qū)別和用途,很多網(wǎng)友都把md5說成是加密算法,這是嚴(yán)重不正確的啊。哈希函數(shù):MD5,SHA 是沒有密鑰的,相當(dāng)與指紋的概念,因此也是不可逆的; md5是128位的,SHA有不同的算法,有128,256等位。。。如SHA-256,SHA-384然后 就是 Base64,這更加不屬于加密算法的范圍了,它只是將byte[]數(shù)組進(jìn)行了轉(zhuǎn)換,為什么要轉(zhuǎn)換呢?就是因?yàn)楹芏嗉用芎蟮拿芪暮笳咭恍┨厥獾腷yte[]數(shù)組需要顯示出來,或者需要進(jìn)行傳遞(電子郵件),但是直接轉(zhuǎn)換就會(huì)導(dǎo)致很多不可顯示的字符,會(huì)丟失一些信息,因此就轉(zhuǎn)換位Base64編碼,這些都是可顯示的字符。所以轉(zhuǎn)換后,長(zhǎng)度會(huì)增加。它是可逆的。 再就是 3DES,DES 這才是加密算法,因此也是可逆的,加解密需要密鑰,也就是你說的key最后是 RSA ,這是公鑰密碼,也就是加密和解密密鑰不同,也是可逆的。

羅列了這么多知識(shí)點(diǎn), 我想這篇文章你應(yīng)該有收藏的必要了吧,為了更形象,更好玩, 我從網(wǎng)上找了一些在線工具:

1.1-Base64

http://www1.tc711.com/tool/BASE64.htm

base641.png
base642.png

可以按出來這是可逆的編解碼,注意不是加密幺!!!

1.2-MD5

http://tool.chinaz.com/Tools/MD5.aspx?q=32324&md5type=1

md5.png

其實(shí)這個(gè)也不能叫加密工具幺,今晚寫到這里吧, 眼睛很累了,明天把這篇文章寫完。

1.3-SHA-1,SHA-2,SHA-256,SHA-512,SHA-3

好吧,哈希的工具找到了一個(gè)更好的工具連接,里面也有MD5.里面還有哈希的一些說明。
http://www.atool.org/hash.php 這個(gè)鏈接值的收藏一下, 主要是用到哈希的時(shí)候可以經(jīng)常用。

SHA.png


2.1 AES DES

以上我們主要說了哈希算法和數(shù)字證書的一些知識(shí), 現(xiàn)在我們看一下對(duì)稱加密的一些在線工具
DES http://e-file.arkoo.com/tools/des3.htm
這個(gè)鏈接可謂非常干凈好用,形象直觀可逆過程,哈哈。

Des.png

AES http://www.seacha.com/tools/aes.html
AEs.png

忽然發(fā)現(xiàn)這個(gè)在線工具也還湊合http://encode.chahuo.com/

all.png

如此般, 對(duì)稱加密基本上都弄完了,現(xiàn)在我們只簡(jiǎn)單的了解下非對(duì)稱加解密的RSA,上面的過程我們已經(jīng)說的非常詳細(xì)了吧。重點(diǎn)已經(jīng)用黑色字體標(biāo)注出來了。

加密數(shù)據(jù)


    RSAEncryptor *rsa = [[RSAEncryptor alloc] init];  
    NSLog(@"encryptor using rsa");  
    NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"der"];  
    NSLog(@"public key: %@", publicKeyPath);  
    [rsa loadPublicKeyFromFile:publicKeyPath];  
  
    NSString *securityText = @"hello ~";  
    NSString *encryptedString = [rsa rsaEncryptString:securityText];  
    NSLog(@"encrypted data: %@", encryptedString);  

解密數(shù)據(jù)在

iOS下解碼需要先加載private key, 之后在對(duì)數(shù)據(jù)解碼. 解碼的時(shí)候先進(jìn)行Base64 decode, 之后在用private key decrypt加密數(shù)據(jù).

    NSLog(@"decryptor using rsa");  
    [rsa loadPrivateKeyFromFile:[[NSBundle mainBundle] pathForResource:@"private_key" ofType:@"p12"] password:@"123456"];  
    NSString *decryptedString = [rsa rsaDecryptString:encryptedString];  
    NSLog(@"decrypted data: %@", decryptedString);  

具體詳細(xì)文章可以參考鏈接
http://witcheryne.iteye.com/blog/2171850
http://www.cocoachina.com/bbs/read.php?tid=166990
在支付寶支付過程中就使用了RSA加密。

在在這里有必要提醒下小編自己, 有時(shí)間需要研究下蘋果證書的工作機(jī)制。


弄到這里, 我主要是找一些代碼給大家用,看看我自己先建一個(gè)工程吧。



//  Created by Lcq on 15/12/16.
//  Copyright ? 2015年 Lcq. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Helper : NSObject

//MD5
+ (NSString *) md5:(NSString *)str;

//Base64
+ (NSString *)base64StringFromText:(NSString *)text;
+ (NSString *)textFromBase64String:(NSString *)base64;
+ (NSString *)base64EncodedStringFrom:(NSData *)data;

//DES加密
+(NSString *)encryptSting:(NSString *)sText key:(NSString *)key andDesiv:(NSString *)ivDes;

//DES解密
+(NSString *)decryptWithDESString:(NSString *)sText key:(NSString *)key andiV:(NSString *)iv;

//AES加密
+ (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv withNSData:(NSData *)data;

//AES解密
+ (NSData *)AES128DecryptWithKey:(NSString *)key iv:(NSString *)iv withNSData:(NSData *)data;

@end


#import "Helper.h"
#import <CommonCrypto/CommonHMAC.h>
#import<CommonCrypto/CommonCryptor.h>
static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define LocalStr_None  @""
@implementation Helper

//Md5
+ (NSString *) md5:(NSString *)str {
    if (str == nil) {
        return nil;
    }
    const char *cStr = [str 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]
            ];
}

//轉(zhuǎn)化為Base64
+ (NSString *)base64StringFromText:(NSString *)text
{
    if (text && ![text isEqualToString:LocalStr_None]) {
        //取項(xiàng)目的bundleIdentifier作為KEY  改動(dòng)了此處
        //NSString *key = [[NSBundle mainBundle] bundleIdentifier];
        NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding];
        //IOS 自帶DES加密 Begin  改動(dòng)了此處
        //data = [self DESEncrypt:data WithKey:key];
        //IOS 自帶DES加密 End
        return [self base64EncodedStringFrom:data];
    }
    else {
        return LocalStr_None;
    }
}

//由base64轉(zhuǎn)化
+ (NSString *)textFromBase64String:(NSString *)base64
{
    if (base64 && ![base64 isEqualToString:LocalStr_None]) {
        //取項(xiàng)目的bundleIdentifier作為KEY   改動(dòng)了此處
        //NSString *key = [[NSBundle mainBundle] bundleIdentifier];
        NSData *data = [self dataWithBase64EncodedString:base64];
        //IOS 自帶DES解密 Begin    改動(dòng)了此處
        //data = [self DESDecrypt:data WithKey:key];
        //IOS 自帶DES加密 End
        return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    }
    else {
        return LocalStr_None;
    }
}

//DES加密
+(NSString *)encryptSting:(NSString *)sText key:(NSString *)key andDesiv:(NSString *)ivDes
{
    if ((sText == nil || sText.length == 0)
        || (sText == nil || sText.length == 0)
        || (ivDes == nil || ivDes.length == 0)) {
        return @"";
    }
    //gb2312 編碼
    NSStringEncoding encoding =CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
    NSData* encryptData = [sText dataUsingEncoding:encoding];
    size_t  dataInLength = [encryptData length];
    const void *   dataIn = (const void *)[encryptData bytes];
    
    CCCryptorStatus ccStatus = nil;
    uint8_t *dataOut = NULL; //可以理解位type/typedef 的縮寫(有效的維護(hù)了代碼,比如:一個(gè)人用int,一個(gè)人用long。最好用typedef來定義)
    size_t dataOutMoved = 0;
    size_t    dataOutAvailable = (dataInLength + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);  dataOut = malloc( dataOutAvailable * sizeof(uint8_t));
    memset((void *)dataOut, 0x0, dataOutAvailable);//將已開辟內(nèi)存空間buffer的首 1 個(gè)字節(jié)的值設(shè)為值 0
    const void *iv = (const void *) [ivDes cStringUsingEncoding:NSASCIIStringEncoding];
    //CCCrypt函數(shù) 加密/解密
    ccStatus = CCCrypt(kCCEncrypt,//  加密/解密
                       kCCAlgorithmDES,//  加密根據(jù)哪個(gè)標(biāo)準(zhǔn)(des,3des,aes。。。。)
                       kCCOptionPKCS7Padding,//  選項(xiàng)分組密碼算法(des:對(duì)每塊分組加一次密  3DES:對(duì)每塊分組加三個(gè)不同的密)
                       [key UTF8String],  //密鑰    加密和解密的密鑰必須一致
                       kCCKeySizeDES,//   DES 密鑰的大小(kCCKeySizeDES=8)
                       iv, //  可選的初始矢量
                       dataIn, // 數(shù)據(jù)的存儲(chǔ)單元
                       dataInLength,// 數(shù)據(jù)的大小
                       (void *)dataOut,// 用于返回?cái)?shù)據(jù)
                       dataOutAvailable,
                       &dataOutMoved);
    
    //編碼 base64
    NSData *data = [NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved];
    Byte *bytes = (Byte *)[data bytes];
    //下面是Byte 轉(zhuǎn)換為16進(jìn)制。
    NSString *hexStr=@"";
    for(int i=0;i<[data length];i++){
        NSString *newHexStr = [NSString stringWithFormat:@"%x",bytes[i]&0xff];///16進(jìn)制數(shù)
        if([newHexStr length]==1)
            hexStr = [NSString stringWithFormat:@"%@0%@",hexStr,newHexStr];
        else
            hexStr = [NSString stringWithFormat:@"%@%@",hexStr,newHexStr];
    }
    free(dataOut);
    return hexStr;
}

//DES解密
+(NSString *)decryptWithDESString:(NSString *)sText key:(NSString *)key andiV:(NSString *)iv
{
    if ((sText == nil || sText.length == 0)
        || (sText == nil || sText.length == 0)
        || (iv == nil || iv.length == 0)) {
        return @"";
    }
    const void *dataIn;
    size_t dataInLength;
    char *myBuffer = (char *)malloc((int)[sText length] / 2 + 1);
    bzero(myBuffer, [sText length] / 2 + 1);
    for (int i = 0; i < [sText length] - 1; i += 2) {
        unsigned int anInt;
        NSString * hexCharStr = [sText substringWithRange:NSMakeRange(i, 2)];
        NSScanner * scanner = [[NSScanner alloc] initWithString:hexCharStr];
        [scanner scanHexInt:&anInt];
        myBuffer[i / 2] = (char)anInt;
    }
    
    NSData *decryptData =[NSData dataWithBytes:myBuffer length:[sText length] / 2 ];//轉(zhuǎn)成utf-8并decode
    dataInLength = [decryptData length];
    dataIn = [decryptData bytes];
    free(myBuffer);
    CCCryptorStatus ccStatus = nil;
    uint8_t *dataOut = NULL; //可以理解位type/typedef 的縮寫(有效的維護(hù)了代碼,比如:一個(gè)人用int,一個(gè)人用long。最好用typedef來定義)
    size_t dataOutAvailable = 0; //size_t  是操作符sizeof返回的結(jié)果類型
    size_t dataOutMoved = 0;
    
    dataOutAvailable = (dataInLength + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);
    dataOut = malloc( dataOutAvailable * sizeof(uint8_t));
    memset((void *)dataOut, 0x0, dataOutAvailable);//將已開辟內(nèi)存空間buffer的首 1 個(gè)字節(jié)的值設(shè)為值 0
    
    const void *ivDes = (const void *) [iv cStringUsingEncoding:NSASCIIStringEncoding];
    //CCCrypt函數(shù) 加密/解密
    ccStatus = CCCrypt(kCCDecrypt,//  加密/解密
                       kCCAlgorithmDES,//  加密根據(jù)哪個(gè)標(biāo)準(zhǔn)(des,3des,aes。。。。)
                       kCCOptionPKCS7Padding,//  選項(xiàng)分組密碼算法(des:對(duì)每塊分組加一次密  3DES:對(duì)每塊分組加三個(gè)不同的密)
                       [key UTF8String],  //密鑰    加密和解密的密鑰必須一致
                       kCCKeySizeDES,//   DES 密鑰的大小(kCCKeySizeDES=8)
                       ivDes, //  可選的初始矢量
                       dataIn, // 數(shù)據(jù)的存儲(chǔ)單元
                       dataInLength,// 數(shù)據(jù)的大小
                       (void *)dataOut,// 用于返回?cái)?shù)據(jù)
                       dataOutAvailable,
                       &dataOutMoved);
    
    NSStringEncoding encoding =CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
    
    NSString *result  = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved] encoding:encoding];
    free(dataOut);
    return result;
}

//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;

}

/******************************************************************************
 函數(shù)名稱 : + (NSData *)dataWithBase64EncodedString:(NSString *)string
 函數(shù)描述 : base64格式字符串轉(zhuǎn)換為文本數(shù)據(jù)
 輸入?yún)?shù) : (NSString *)string
 輸出參數(shù) : N/A
 返回參數(shù) : (NSData *)
 備注信息 :
 ******************************************************************************/
+ (NSData *)dataWithBase64EncodedString:(NSString *)string
{
    if (string == nil)
        [NSException raise:NSInvalidArgumentException format:nil];
    if ([string length] == 0)
        return [NSData data];
    
    static char *decodingTable = NULL;
    if (decodingTable == NULL)
    {
        decodingTable = malloc(256);
        if (decodingTable == NULL)
            return nil;
        memset(decodingTable, CHAR_MAX, 256);
        NSUInteger i;
        for (i = 0; i < 64; i++)
            decodingTable[(short)encodingTable[i]] = i;
    }
    
    const char *characters = [string cStringUsingEncoding:NSASCIIStringEncoding];
    if (characters == NULL)     //  Not an ASCII string!
        return nil;
    char *bytes = malloc((([string length] + 3) / 4) * 3);
    if (bytes == NULL)
        return nil;
    NSUInteger length = 0;
    
    NSUInteger i = 0;
    while (YES)
    {
        char buffer[4];
        short bufferLength;
        for (bufferLength = 0; bufferLength < 4; i++)
        {
            if (characters[i] == '\0')
                break;
            if (isspace(characters[i]) || characters[i] == '=')
                continue;
            buffer[bufferLength] = decodingTable[(short)characters[i]];
            if (buffer[bufferLength++] == CHAR_MAX)      //  Illegal character!
            {
                free(bytes);
                return nil;
            }
        }
        
        if (bufferLength == 0)
            break;
        if (bufferLength == 1)      //  At least two characters are needed to produce one byte!
        {
            free(bytes);
            return nil;
        }
        
        //  Decode the characters in the buffer to bytes.
        bytes[length++] = (buffer[0] << 2) | (buffer[1] >> 4);
        if (bufferLength > 2)
            bytes[length++] = (buffer[1] << 4) | (buffer[2] >> 2);
        if (bufferLength > 3)
            bytes[length++] = (buffer[2] << 6) | buffer[3];
    }
    
    bytes = realloc(bytes, length);
    return [NSData dataWithBytesNoCopy:bytes length:length];
}

/******************************************************************************
 函數(shù)名稱 : + (NSString *)base64EncodedStringFrom:(NSData *)data
 函數(shù)描述 : 文本數(shù)據(jù)轉(zhuǎn)換為base64格式字符串
 輸入?yún)?shù) : (NSData *)data
 輸出參數(shù) : N/A
 返回參數(shù) : (NSString *)
 備注信息 :
 ******************************************************************************/
+ (NSString *)base64EncodedStringFrom:(NSData *)data
{
    if ([data length] == 0)
        return @"";
    
    char *characters = malloc((([data length] + 2) / 3) * 4);
    if (characters == NULL)
        return nil;
    NSUInteger length = 0;
    
    NSUInteger i = 0;
    while (i < [data length])
    {
        char buffer[3] = {0,0,0};
        short bufferLength = 0;
        while (bufferLength < 3 && i < [data length])
            buffer[bufferLength++] = ((char *)[data bytes])[i++];
        
        //  Encode the bytes in the buffer to four characters, including padding "=" characters if necessary.
        characters[length++] = encodingTable[(buffer[0] & 0xFC) >> 2];
        characters[length++] = encodingTable[((buffer[0] & 0x03) << 4) | ((buffer[1] & 0xF0) >> 4)];
        if (bufferLength > 1)
            characters[length++] = encodingTable[((buffer[1] & 0x0F) << 2) | ((buffer[2] & 0xC0) >> 6)];
        else characters[length++] = '=';
        if (bufferLength > 2)
            characters[length++] = encodingTable[buffer[2] & 0x3F];
        else characters[length++] = '=';
    }
    
    return [[NSString alloc] initWithBytesNoCopy:characters length:length encoding:NSASCIIStringEncoding freeWhenDone:YES];
}

@end

以上是接口和實(shí)現(xiàn)文件, 現(xiàn)在我們來看看調(diào)用



- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    //MD5
    NSString *md5Str = [Helper md5:@"我愛你"];
    NSLog(@"md5Str is %@",md5Str);//Log is 4F2016C6B934D55BD7120E5D0E62CCE3
    
    //Base64
    NSString *Base64Str = [Helper base64StringFromText:@"我愛你"];
    NSLog(@"Base64Str is %@",Base64Str);//Log is 5oiR54ix5L2g
    
    NSString *oriBase64Str = [Helper textFromBase64String:Base64Str];
    NSLog(@"oriBase64Str is %@",oriBase64Str);//Log is  我愛你
    
    //DES
    NSString *desEnStr = [Helper encryptSting:@"我愛你" key:@"521" andDesiv:@"521"];
    NSLog(@"desEnStr is %@",desEnStr);//Log is  389280aa791ee933
    NSString *desDeStr =[Helper decryptWithDESString:desEnStr key:@"521" andiV:@"521"];
    NSLog(@"desDeStr is %@",desDeStr);//Log is  我愛你
    
    //AES
    NSData *aesEnData = [Helper AES128EncryptWithKey:@"521" iv:@"521" withNSData:[@"我愛你" dataUsingEncoding:NSUTF8StringEncoding]];
    NSString *aesEnStr = [Helper base64EncodedStringFrom:aesEnData];
    NSLog(@"aesEnStr is %@",aesEnStr);//Log is HZKhnRLlQ8XjMjpelOAwsQ==
    
    NSData *aesDeData = [Helper AES128DecryptWithKey:@"521" iv:@"521" withNSData:aesEnData];
    NSString *aesDEStr = [Helper base64EncodedStringFrom:aesDeData];
    NSString *result = [Helper textFromBase64String:aesDEStr];
    NSLog(@"aesDEStr is %@ and result is %@",aesDEStr,result);//Log is aesDEStr is 5oiR54ix5L2gAAAAAAAAAA== and result is 我愛你
    
    return YES;
}

寫到這里, 產(chǎn)生了一個(gè)問題, 就是上面的AES加密最終生成的Base64字符串和工具不一樣 ,不知道是什么問題, 還請(qǐng)高手幫忙解答一下。
大家也可以嘗試下網(wǎng)上其他人的代碼
//AES可以參考一個(gè)鏈接 http://www.tuicool.com/articles/UVRjmyN


好了, 文章的最后,我們來簡(jiǎn)單學(xué)習(xí)和了解下cookie在客戶端里的應(yīng)用
首先帶大家了解下什么是cookie吧

cookie.jpg

這是維基百科里一段對(duì)cookie的描述,可見cookie是服務(wù)器生成的發(fā)給客戶端,具體應(yīng)用例如:我們打開淘寶的某一個(gè)頁面,登陸了賬號(hào)和密碼, 當(dāng)我們?cè)偬D(zhuǎn)到其他淘寶界面的時(shí)候,我們不必每一次都重新登陸界面, 這就是cookie的作用, 其實(shí)cookie還能記錄用戶選的訂單, 至于深一層的了解, 我還不是很清楚, 因?yàn)闆]有學(xué)過前端的開發(fā),感興趣的讀者可以自行了解。

其實(shí)cookie也可以在客戶端使用的。NSHTTPCookieStorage在iOS上是一個(gè)單例。那么首先我們通過代碼的方式看看怎么添加cookie和刪除cookie,



///增加cookies
+ (void)addCookiesToRequest:(NSMutableDictionary *)cookieDic
{
    NSEnumerator * enumeratorKey = [cookieDic keyEnumerator];
    for (NSObject * key in enumeratorKey) {
        NSHTTPCookie *userInfoCookie = [NSHTTPCookie cookieWithProperties:
                                        [NSDictionary dictionaryWithObjectsAndKeys:
                                         @".baidu.com", NSHTTPCookieDomain,
                                         @"/", NSHTTPCookiePath,
                                         [NSString stringWithFormat:@"%@",key],  NSHTTPCookieName,
                                         [NSDate dateWithTimeIntervalSinceNow:30*24*3600], NSHTTPCookieExpires,
                                         [NSString stringWithFormat:@"%@",[cookieDic objectForKey:key]], NSHTTPCookieValue,
                                         nil]];
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:userInfoCookie];
        
   
        NSHTTPCookie *txdaiCookie = [NSHTTPCookie cookieWithProperties:
                                        [NSDictionary dictionaryWithObjectsAndKeys:
                                         @".jingdong.com", NSHTTPCookieDomain,
                                         @"/", NSHTTPCookiePath,
                                         [NSString stringWithFormat:@"%@",key],  NSHTTPCookieName,
                                         [NSDate dateWithTimeIntervalSinceNow:30*24*3600], NSHTTPCookieExpires,
                                         [NSString stringWithFormat:@"%@",[cookieDic objectForKey:key]], NSHTTPCookieValue,
                                         nil]];
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:txdaiCookie];
    }
}

同樣刪除cookie也非常簡(jiǎn)單

///刪除基本cookies
+(void)deleteBaseCookie{
    NSHTTPCookie *passportCookie = [NSHTTPCookie cookieWithProperties:
                                    [NSDictionary dictionaryWithObjectsAndKeys:
                                     @".baidu.com", NSHTTPCookieDomain,
                                     @"/", NSHTTPCookiePath,
                                     @"sfut",  NSHTTPCookieName,
                                     @"", NSHTTPCookieValue,
                                     nil]];
    [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:passportCookie];

    NSHTTPCookie *txdaiCookie = [NSHTTPCookie cookieWithProperties:
                                 [NSDictionary dictionaryWithObjectsAndKeys:
                                  @".jingdong.com", NSHTTPCookieDomain,
                                  @"/", NSHTTPCookiePath,
                                  @"sfut",  NSHTTPCookieName,
                                  @"", NSHTTPCookieValue,
                                  nil]];
    [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:txdaiCookie];
}

那么最后一個(gè)問題就是我們?cè)诳蛻舳耸裁辞闆r下才添加或者刪除cookie呢。
當(dāng)我們的應(yīng)用在加載一個(gè)wap頁面的時(shí)候,可能wap需要知道客戶端的一些信息, 比如你是登陸狀態(tài)還是什么狀態(tài),因?yàn)檫@時(shí)候我們就可以設(shè)置cookie,wap可以拿到請(qǐng)求的cookie
當(dāng)然需要注意的是在wap將要銷毀的時(shí)候,要把cookie信息給移除掉。

最近沒寫文章, 以后要棒棒的去寫文章,如果你喜歡, 就關(guān)注我把。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評(píng)論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,556評(píng)論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評(píng)論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,778評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,218評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,436評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,969評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,795評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,993評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,229評(píng)論 3 347
  • 開封第一講書人閱讀 34,659評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評(píng)論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,687評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,990評(píng)論 2 374

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