這篇文章不是研究性的東西围橡,主要是簡(jiǎn)單的一些知識(shí)暖混, 開(kāi)篇如此, 我盡量不讓讀者失望翁授。
首先羅列一些知識(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ù)字簽名辽剧, 通過(guò)一個(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>公鑰加密私鑰解密, 沒(méi)問(wèn)題,也可以說(shuō)是"公共密鑰加密系統(tǒng)"私鑰加密公鑰解密,一般不這么說(shuō)衫冻,應(yīng)叫"私鑰簽名,公鑰驗(yàn)證",也可以說(shuō)是“公共密鑰簽名系統(tǒng)”</b>
引用一段總結(jié)的話:
<b>
公鑰加密私鑰解密诀紊, 沒(méi)問(wèn)題,也可以說(shuō)是"公共密鑰加密系統(tǒng)"私鑰加密公鑰解密,一般不這么說(shuō),應(yīng)叫"私鑰簽名,公鑰驗(yàn)證",也可以說(shuō)是“公共密鑰簽名系統(tǒng)”再來(lái)說(shuō)一下"公共密鑰簽名系統(tǒng)"目的:(如果暈就多看幾遍隅俘,這個(gè)沒(méi)搞清邻奠,后面的代碼就更暈)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(信息)] 如能解開(kāi),證明該 [ 私鑰(MD5(信息))]是A發(fā)送的3.再比效[MD5(信息)!]與[(MD5(信息)] 如果相同,表示(信息)在傳遞過(guò)程中沒(méi)有被他人修改過(guò)
</b>
OK, 到現(xiàn)在為止唧喉, 你已經(jīng)懂得了公鑰, 私鑰忍抽, 以及數(shù)字證書的概念了八孝, 當(dāng)然你也知道什么是對(duì)稱加密和非對(duì)稱加密,有可能你不是很清楚鸠项,為了讓你更清楚干跛,給你再講個(gè)活生生的例子,這個(gè)例子還要從我的戀愛(ài)說(shuō)起祟绊, 高中的時(shí)候喜歡上一個(gè)女生楼入, 那時(shí)候青春年少哥捕,還喜歡用紙質(zhì)給她寫情書, 每天寫一些“透明的”文字很繁瑣嘉熊,于是有一天遥赚,我忽然一個(gè)念想,把情書改成用漢語(yǔ)拼音寫abcd……xyz, 原來(lái)字母是a就用z代替阐肤,b用y代替凫佛,c用x代替,……z用a代替孕惜, 這樣愧薛,一個(gè)只有我們倆能看的懂的情書就這樣誕生了。其實(shí)現(xiàn)在想想衫画, 這不正是一種對(duì)稱式加密么毫炉。哈哈。
說(shuō)完了故事削罩,再來(lái)普及下一點(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í)間問(wèn)題, 我就不給大家找了腾供。
4幾種非對(duì)稱性加密算法:RSA,DSA,ECC
RSA和DSA的安全性及其它各方面性能都差不多仆邓,而ECC較之則有著很多的性能優(yōu)越,包括處理速度伴鳖,帶寬要求节值,存儲(chǔ)空間等等
5幾種線性散列算法(簽名算法):MD5,SHA1,HMAC
這幾種算法只生成一串不可逆的密文,經(jīng)常用其效驗(yàn)數(shù)據(jù)傳輸過(guò)程中是否經(jīng)過(guò)修改榜聂,因?yàn)橄嗤纳伤惴▽?duì)于同一明文只會(huì)生成唯一的密文搞疗,若相同算法生成的密文不同,則證明傳輸數(shù)據(jù)進(jìn)行過(guò)了修改须肆。通常在數(shù)據(jù)傳說(shuō)過(guò)程前匿乃,使用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ù)雜的過(guò)程阳懂,密鑰的管理直接決定著他的安全性梅尤,因此當(dāng)數(shù)據(jù)量很小時(shí),我們可以考慮采用非對(duì)稱加密算法岩调。
在實(shí)際的操作過(guò)程中<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>如果在選定了加密算法后葱淳,那采用多少位的密鑰呢?一般來(lái)說(shuō)抛姑,密鑰越長(zhǎng)赞厕,運(yùn)行的速度就越慢,應(yīng)該根據(jù)的我們實(shí)際需要的安全級(jí)別來(lái)選擇定硝,一般來(lái)說(shuō)皿桑,RSA建議采用1024位的數(shù)字,ECC建議采用160位蔬啡,AES采用128為即可诲侮。
需要注意的是:
哈希函數(shù),比如MD5,SHA,這些都不是加密算法箱蟆。要注意他們的區(qū)別和用途沟绪,很多網(wǎng)友都把md5說(shuō)成是加密算法,這是嚴(yán)重不正確的啊空猜。哈希函數(shù):MD5绽慈,SHA 是沒(méi)有密鑰的,相當(dāng)與指紋的概念辈毯,因此也是不可逆的坝疼; md5是128位的,SHA有不同的算法漓摩,有128裙士,256等位。管毙。腿椎。如SHA-256,SHA-384然后 就是 Base64,這更加不屬于加密算法的范圍了桌硫,它只是將byte[]數(shù)組進(jìn)行了轉(zhuǎn)換,為什么要轉(zhuǎn)換呢啃炸?就是因?yàn)楹芏嗉用芎蟮拿芪暮笳咭恍┨厥獾腷yte[]數(shù)組需要顯示出來(lái)铆隘,或者需要進(jìn)行傳遞(電子郵件),但是直接轉(zhuǎn)換就會(huì)導(dǎo)致很多不可顯示的字符南用,會(huì)丟失一些信息膀钠,因此就轉(zhuǎn)換位Base64編碼,這些都是可顯示的字符裹虫。所以轉(zhuǎn)換后肿嘲,長(zhǎng)度會(huì)增加。它是可逆的筑公。 再就是 3DES,DES 這才是加密算法雳窟,因此也是可逆的,加解密需要密鑰,也就是你說(shuō)的key最后是 RSA ,這是公鑰密碼匣屡,也就是加密和解密密鑰不同封救,也是可逆的。
羅列了這么多知識(shí)點(diǎn)捣作, 我想這篇文章你應(yīng)該有收藏的必要了吧誉结,為了更形象,更好玩券躁, 我從網(wǎng)上找了一些在線工具:
1.1-Base64
http://www1.tc711.com/tool/BASE64.htm
可以按出來(lái)這是可逆的編解碼惩坑,注意不是加密幺!V鲂唷旭贬!
1.2-MD5
http://tool.chinaz.com/Tools/MD5.aspx?q=32324&md5type=1
其實(shí)這個(gè)也不能叫加密工具幺,今晚寫到這里吧搪泳, 眼睛很累了稀轨,明天把這篇文章寫完。
1.3-SHA-1,SHA-2,SHA-256,SHA-512,SHA-3
好吧岸军,哈希的工具找到了一個(gè)更好的工具連接奋刽,里面也有MD5.里面還有哈希的一些說(shuō)明。
http://www.atool.org/hash.php 這個(gè)鏈接值的收藏一下艰赞, 主要是用到哈希的時(shí)候可以經(jīng)常用佣谐。
2.1 AES DES
以上我們主要說(shuō)了哈希算法和數(shù)字證書的一些知識(shí), 現(xiàn)在我們看一下對(duì)稱加密的一些在線工具
DES http://e-file.arkoo.com/tools/des3.htm
這個(gè)鏈接可謂非常干凈好用方妖,形象直觀可逆過(guò)程狭魂,哈哈。
AES http://www.seacha.com/tools/aes.html
忽然發(fā)現(xiàn)這個(gè)在線工具也還湊合http://encode.chahuo.com/
如此般, 對(duì)稱加密基本上都弄完了雌澄,現(xiàn)在我們只簡(jiǎn)單的了解下非對(duì)稱加解密的RSA,上面的過(guò)程我們已經(jīng)說(shuō)的非常詳細(xì)了吧斋泄。重點(diǎn)已經(jīng)用黑色字體標(biāo)注出來(lái)了。
加密數(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
在支付寶支付過(guò)程中就使用了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來(lái)定義)
size_t dataOutMoved = 0;
size_t dataOutAvailable = (dataInLength + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1); dataOut = malloc( dataOutAvailable * sizeof(uint8_t));
memset((void *)dataOut, 0x0, dataOutAvailable);//將已開(kāi)辟內(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來(lái)定義)
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);//將已開(kāi)辟內(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)在我們來(lái)看看調(diào)用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//MD5
NSString *md5Str = [Helper md5:@"我愛(ài)你"];
NSLog(@"md5Str is %@",md5Str);//Log is 4F2016C6B934D55BD7120E5D0E62CCE3
//Base64
NSString *Base64Str = [Helper base64StringFromText:@"我愛(ài)你"];
NSLog(@"Base64Str is %@",Base64Str);//Log is 5oiR54ix5L2g
NSString *oriBase64Str = [Helper textFromBase64String:Base64Str];
NSLog(@"oriBase64Str is %@",oriBase64Str);//Log is 我愛(ài)你
//DES
NSString *desEnStr = [Helper encryptSting:@"我愛(ài)你" 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 我愛(ài)你
//AES
NSData *aesEnData = [Helper AES128EncryptWithKey:@"521" iv:@"521" withNSData:[@"我愛(ài)你" 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 我愛(ài)你
return YES;
}
寫到這里, 產(chǎn)生了一個(gè)問(wèn)題邓梅, 就是上面的AES加密最終生成的Base64字符串和工具不一樣 脱盲,不知道是什么問(wèn)題, 還請(qǐng)高手幫忙解答一下日缨。
大家也可以嘗試下網(wǎng)上其他人的代碼
//AES可以參考一個(gè)鏈接 http://www.tuicool.com/articles/UVRjmyN
好了钱反, 文章的最后,我們來(lái)簡(jiǎn)單學(xué)習(xí)和了解下cookie在客戶端里的應(yīng)用
首先帶大家了解下什么是cookie吧
這是維基百科里一段對(duì)cookie的描述,可見(jiàn)cookie是服務(wù)器生成的發(fā)給客戶端面哥,具體應(yīng)用例如:我們打開(kāi)淘寶的某一個(gè)頁(yè)面哎壳,登陸了賬號(hào)和密碼, 當(dāng)我們?cè)偬D(zhuǎn)到其他淘寶界面的時(shí)候幢竹,我們不必每一次都重新登陸界面耳峦, 這就是cookie的作用, 其實(shí)cookie還能記錄用戶選的訂單焕毫, 至于深一層的了解蹲坷, 我還不是很清楚, 因?yàn)闆](méi)有學(xué)過(guò)前端的開(kāi)發(fā)邑飒,感興趣的讀者可以自行了解循签。
其實(shí)cookie也可以在客戶端使用的。NSHTTPCookieStorage在iOS上是一個(gè)單例疙咸。那么首先我們通過(guò)代碼的方式看看怎么添加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è)問(wèn)題就是我們?cè)诳蛻舳耸裁辞闆r下才添加或者刪除cookie呢。
當(dāng)我們的應(yīng)用在加載一個(gè)wap頁(yè)面的時(shí)候撒轮,可能wap需要知道客戶端的一些信息乞旦, 比如你是登陸狀態(tài)還是什么狀態(tài),因?yàn)檫@時(shí)候我們就可以設(shè)置cookie,wap可以拿到請(qǐng)求的cookie
當(dāng)然需要注意的是在wap將要銷毀的時(shí)候题山,要把cookie信息給移除掉兰粉。
最近沒(méi)寫文章, 以后要棒棒的去寫文章顶瞳,如果你喜歡玖姑, 就關(guān)注我把。