對稱密鑰加密
對稱加密相對好理解,加密方和解密方使用的是同一個密鑰。
常見的對稱密鑰加密有AES、DES 等。
MD5
MD5是一個哈希算法,對同一個明文生成的密文(哈希值)是統(tǒng)一的。MD5相較于普通加密來說還有一個優(yōu)點(diǎn):MD5生成的密文長度很短(16位或者32位字符)。全稱MD5消息摘要算法(MD5 Message-Digest Algorithm)。
非對稱密鑰加密
非對稱密鑰加密,又稱為公開密鑰加密。
非對稱密鑰加密需要兩個密鑰,一個是公開密鑰,一個是私有密鑰。私有密鑰用來加密,公開密鑰用來解密。私有密鑰由加密方保管,公有密鑰則公布出來。
實(shí)際上,私有密鑰和共有密鑰在數(shù)學(xué)上是有一定的關(guān)系的。但是僅僅從共有密鑰是推斷不出私有密鑰的,這也是共有密鑰可以公布出來的原因。
通過共有密鑰推斷私有密鑰和質(zhì)數(shù)分解有關(guān)。目前質(zhì)數(shù)分解沒有特別快的算法,通常是通過暴力枚舉的方法來分解。當(dāng)質(zhì)數(shù)非常大時(如2的1024次方級別),暴力分解質(zhì)數(shù)是不現(xiàn)實(shí)的,因此非對稱加密是安全的。
非對稱加密的安全還依賴于加密方對私鑰的管理,一旦私鑰暴露,也就毫無加密可言。
常見的非對稱加密有RSA、DSA。
數(shù)字簽名
數(shù)字簽名用的是非對稱加密,公開密鑰在數(shù)據(jù)接收方,數(shù)字簽名的作用是保證:
- 保證數(shù)據(jù)沒有沒有被篡改過
- 保證數(shù)據(jù)是經(jīng)過我認(rèn)證的

- 首先算出原始數(shù)據(jù)的摘要。這里的算法要保證:如果原始數(shù)據(jù)有任何變化,則摘要也會發(fā)生變化;對同一份原始數(shù)據(jù),使用相同的算法,計(jì)算出的摘要是相同的。這一步使用的算法通常是MD5消息摘要算法。
- 生成一對公鑰和私鑰,使用非對稱加密方式,用私鑰對上一步生成的摘要進(jìn)行加密,加密的結(jié)果就是數(shù)字簽名。
- 在返回?cái)?shù)據(jù)時,將原始數(shù)據(jù)和數(shù)字簽名一起返回給請求數(shù)據(jù)方。
接到數(shù)據(jù)之后就行驗(yàn)證數(shù)據(jù)的完整性:

- 首先用含有的公鑰對數(shù)字簽名進(jìn)行解密,如果能夠解密成功,說明返回的數(shù)據(jù)是經(jīng)過數(shù)據(jù)發(fā)送方認(rèn)證的(否則數(shù)據(jù)發(fā)送方不會對該數(shù)據(jù)加密)。
- 對原始的數(shù)據(jù)使用MD5算法,生成原始數(shù)據(jù)的摘要。
- 對比第一步和第二步生成的摘要,如果生成的摘要相等,說明原始數(shù)據(jù)沒有被篡改過。
由此,通過數(shù)字簽名可以達(dá)到確保數(shù)據(jù)沒有被篡改過以及數(shù)據(jù)是合法的目的。
DES加解密
這里使用框架提供的des加解密庫:
首先引入頭文件 #import CommonCrypto/CommonCryptor.h
主要的加解密函數(shù)如下:
/*字符串加密
*參數(shù)
*plainText : 加密明文
*key : 密鑰 64位
*/
+ (NSString *) encryptUseDES:(NSString *)plainText key:(NSString *)key
{
NSString *ciphertext = nil;
const char *textBytes = [plainText UTF8String];
NSUInteger dataLength = [plainText length];
unsigned char buffer[1024];
memset(buffer, 0, sizeof(char));
Byte iv[] = {1,2,3,4,5,6,7,8};
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES,
kCCOptionPKCS7Padding,
[key UTF8String], kCCKeySizeDES,
iv,
textBytes, dataLength,
buffer, 1024,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
NSData *data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesEncrypted];
ciphertext = [[[NSString alloc] initWithData:[GTMBase64 encodeData:data] encoding:NSUTF8StringEncoding] autorelease];
}
return ciphertext;
}
//解密
+ (NSString *) decryptUseDES:(NSString*)cipherText key:(NSString*)key
{
NSData* cipherData = [GTMBase64 decodeString:cipherText];
unsigned char buffer[1024];
memset(buffer, 0, sizeof(char));
size_t numBytesDecrypted = 0;
Byte iv[] = {1,2,3,4,5,6,7,8};
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmDES,
kCCOptionPKCS7Padding,
[key UTF8String],
kCCKeySizeDES,
iv,
[cipherData bytes],
[cipherData length],
buffer,
1024,
&numBytesDecrypted);
NSString* plainText = nil;
if (cryptStatus == kCCSuccess) {
NSData* data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesDecrypted];
plainText = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
}
return plainText;
}
MD5加密
MD5加密是不可逆的
MD5實(shí)現(xiàn)方法(16位):
+ (NSString *)md5:(NSString *)str
{
constchar *concat_str = [strUTF8String];
unsignedchar result[CC_MD5_DIGEST_LENGTH];
CC_MD5(concat_str, (unsignedint)strlen(concat_str), result);
NSMutableString *hash = [NSMutableStringstring];
for (int i =0; i <16; i++){
[hashappendFormat:@"%02X", result[i]];
}
return [hashuppercaseString];
}
AES加密
對稱加密,密鑰key
常用的,詳解:
h文件內(nèi)容:
#import
@class NSString;
@interface NSData (Encryption)
- (NSData *)AESOverCycle:(NSString *)key; //加密
- (NSData *)AESRelaes:(NSString *)key; //解密
@end
m文件內(nèi)容:
加密:
@implementation NSData (Encryption)
- (NSData *)AESOverCycle:(NSString *)key {
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCBlockSizeAES128,
NULL,
[self bytes], dataLength,
buffer, bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
解密:
- (NSData *)AESRelaes:(NSString *)key {
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCBlockSizeAES128,
NULL,
[self bytes], dataLength,
buffer, bufferSize,
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer);
return nil;
}
@end
Base64編碼與解碼
Base64編碼是6個二進(jìn)制位一編碼, ASCII碼是8個二進(jìn)制位一編碼,所以轉(zhuǎn)換成字符串后會比ASCII內(nèi)容要多。其使用64個字符來對任意數(shù)據(jù)進(jìn)行編碼。
Base64編碼本質(zhì)上是一種將二進(jìn)制數(shù)據(jù)轉(zhuǎn)成文本數(shù)據(jù)的方案。對于非二進(jìn)制數(shù)據(jù),是先將其轉(zhuǎn)換成二進(jìn)制形式,然后每連續(xù)6比特(2的6次方=64)計(jì)算其十進(jìn)制值,根據(jù)該值在上面的索引表中找到對應(yīng)的字符,最終得到一個文本字符串。
Base64是一個可逆過程,不能用作數(shù)據(jù)加密操作。