專案裡面常用的加密方式base64、AES、MD5、sha-1
1.簡單的概念
明文:加密前的資訊
密文:機密後的資訊
演算法:加密或解密的演算法
金鑰:演算法使用的鑰匙(讀作miyao,正確應該是miyue,但是大家都讀miyao)
2.簡單的例子
將123456每位數字都加1後得到234567,
其中123456就是明文,234567就是密文,加密金鑰就是1,加密演算法是每位加
3.對稱加密和非對稱加密
以上為例,
123456-->234567的加密金鑰就是1,加密演算法是每位+
234567-->123456的解密金鑰也是1,解密演算法是每位-
其中加密演算法(+)和解密演算法(-)相對稱,這種加密演算法就稱作對稱加密,
同樣,如果加密演算法和解密演算法不對稱就稱之為非對稱加密。
4.演算法舉例
對稱加密演算法:DES演算法,3DES演算法,TDEA演算法,Blowfish演算法,RC5演算法,IDEA演算法,AES演算法。
非對稱加密演算法:RSA、Elgamal、揹包演算法、Rabin、D-H、ECC。
經典的雜湊演算法:MD2、MD4、MD5 和 SHA-1(目的是將任意長輸入通過演算法變為固定長輸出,且保證輸入變化一點輸出都不同,且不能反向解密)
下面我們說一下我們常用到的加密手段
1.base64,這個加密手段是一些專案裡面常用到的,一般採用這種加密手段十分好破解,他的加密實際作用不在於保密,你看看經過BASE64編碼後的字串,全部都是由標準鍵盤上面的常規字元組成,這樣編碼後的字串在閘道器之間傳遞不會產生UNICODE字串不能識別或者丟失的現象。你再仔細研究下EMAIL就會發現其實EMAIL就是用base64編碼過後再發送的。然後接收的時候再還原。
還有一種情況下用BASE64編碼也很好,比如一個圖片檔案,或者其他任何二進位制檔案。我可以把它編碼成字串。這樣用XML或者資料庫就能直接以文字的方式來儲存這些檔案了。
下面就說一下他的具體使用了:
首先你要先新增幾個檔案GTMBase64,這個是第三方的庫可以從網路資源中獲取,直接呼叫裡面的演算法
//加密演算法
+(NSData *)encodeData:(NSData *)data {
return [self baseEncode:[data bytes]
length:[data length]
charset:kBase64EncodeChars
padded:YES];
}
//解密演算法
+(NSData *)decodeData:(NSData *)data {
return [self baseDecode:[data bytes]
length:[data length]
charset:kBase64DecodeChars
requirePadding:YES];
}
從程式中我們可以看到無論是加密還是解密他處理的物件都是nsdata型別的
所以我們在加密解密之前要對資料進行二進位制編碼
例項說明:
//使用者名稱
NSData*data_user=[userName_TF.text dataUsingEncoding:NSUTF8StringEncoding];
NSData*Data_U=[GTMBase64 encodeData:data_user];
NSString*username=[[NSString alloc]initWithData:Data_U encoding:NSUTF8StringEncoding];
2.下面說一下MD5加密的作用和用法
首先要知道MD5加密原理和性質,MD5首先他是一個安全的算列演算法,他有兩個特點。其一,輸入兩段明文也就是原始資料,不會得到相同的輸出值。
其二,他的過程是不可逆的也就是說根據輸出值,是不能得到原始的明文的。所以要解密MD5沒有現成的演算法,只能用窮舉法,把可能出現的明文,用MD5演算法雜湊之後,把得到的雜湊值和原始的資料形成一個一對一的對映表,然後在所謂的解密的時候,都是通過這個對映表來查詢其所對應的原始明文。
而絕對沒有一種演算法,可以通過輸出加密後的散搜尋列值算出原始明文。
使用演算法:
- (NSString *)md5Encrypt {
const char *cStr = [self 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]
];
}
直接拓展NSString演算法,直接呼叫這個演算法就可以了用起來十分簡單。
[nsstring md5Encrypt]—>返回值也是一個字串。MD5加密可以生成一個16位的字串或者是32位的字串
3.SHA-1與MD5都是摘要演算法,且為不可逆演算法;
應用角度來講,適用性比安全性重要,兩個演算法長度有所不同,SHA-1 160位,MD5 128位。
如果從安全形度,在計算出摘要後,對摘要進行簽名,可以增加抗抵賴、防篡改的能力
//32位MD5加密方式
+ (NSString *)getMd5_32Bit_String:(NSString *)srcString isUppercase:(BOOL)isUppercase{
const char *cStr = [srcString UTF8String];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5( cStr, strlen(cStr), digest );
NSMutableString *result = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[result appendFormat:@"%02x", digest[i]];
if (isUppercase) {
return [result uppercaseString];
}else{
return result;
}
}
//16位MD5加密方式
+ (NSString *)getMd5_16Bit_String:(NSString *)srcString isUppercase:(BOOL)isUppercase{
//提取32位MD5雜湊的中間16位
NSString *md5_32Bit_String=[self getMd5_32Bit_String:srcString isUppercase:NO];
NSString *result = [[md5_32Bit_String substringToIndex:24] substringFromIndex:8];//即9~25位
if (isUppercase) {
return [result uppercaseString];
}else{
return result;
}
}
//sha1加密方式
+ (NSString *)getSha1String:(NSString *)srcString{
const char *cstr = [srcString cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:srcString.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, data.length, digest);
NSMutableString* result = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
[result appendFormat:@"%02x", digest[i]];
}
return result;
}
//sha256加密方式
+ (NSString *)getSha256String:(NSString *)srcString {
const char *cstr = [srcString cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:srcString.length];
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA1(data.bytes, data.length, digest);
NSMutableString* result = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[result appendFormat:@"%02x", digest[i]];
}
return result;
}
//sha384加密方式
+ (NSString *)getSha384String:(NSString *)srcString {
const char *cstr = [srcString cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:srcString.length];
uint8_t digest[CC_SHA384_DIGEST_LENGTH];
CC_SHA1(data.bytes, data.length, digest);
NSMutableString* result = [NSMutableString stringWithCapacity:CC_SHA384_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA384_DIGEST_LENGTH; i++) {
[result appendFormat:@"%02x", digest[i]];
}
return result;
}
//sha512加密方式
+ (NSString*) getSha512String:(NSString*)srcString {
const char *cstr = [srcString cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:srcString.length];
uint8_t digest[CC_SHA512_DIGEST_LENGTH];
CC_SHA512(data.bytes, data.length, digest);
NSMutableString* result = [NSMutableString stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++)
[result appendFormat:@"%02x", digest[i]];
return result;
}
這是具體的演算法,直接封裝在一個類裡面直接呼叫就可以了使用方法和MD5是一樣的。
4.AES加密演算法。
AES是DES的進化版
這個是我目前使用的具有保密性的一個加密演算法這個加密的時候需要一個key值解密的時候也要需要同樣的key值才可以解密,相當於一個口令。
加密演算法使用
//金鑰加密和解密的時候要用
#define kCryptingKey @"1102130405061708" /// 同上
#define kCryptingIv @"1102130405061708" /// 同上
@implementation Tool
+ (NSString*) encrypt:(NSString*)recource
{
NSData *data = [recource dataUsingEncoding:NSUTF8StringEncoding];
NSData *result = [self AES128EncryptWithKey:kCryptingKey withData:data iv:kCryptingIv];
return [self stringWithHexBytes:result];
}
+ (NSString*) decryptData:(NSData*)recource
{
NSData *decrypt = [self AES128DecryptWithKey:kCryptingKey withData:recource iv:kCryptingIv];
return [[NSString alloc] initWithData:decrypt encoding:NSUTF8StringEncoding];
}
+ (NSString*) decrypt:(NSString*)recource
{
NSData* data=[self decodeFromHexidecimal:recource];
NSData *decrypt = [self AES128DecryptWithKey:kCryptingKey withData:data iv:kCryptingIv];
return [[NSString alloc] initWithData:decrypt encoding:NSUTF8StringEncoding];
}
+ (NSData *) decodeFromHexidecimal:(NSString*)str
{
NSString *command = [NSString stringWithString:str];
command = [command stringByReplacingOccurrencesOfString:@" " withString:@""];
NSMutableData *commandToSend = [[NSMutableData data] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [command length]/2; i++) {
byte_chars[0] = [command characterAtIndex:i*2];
byte_chars[1] = [command characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[commandToSend appendBytes:&whole_byte length:1];
}
return commandToSend;
}
+ (NSData *)AES128EncryptWithKey:(NSString *)key withData:(NSData*)_data iv:(NSString *) iv
{
char keyPtr[kCCKeySizeAES128 + 1];
memset(keyPtr, 0, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];
char ivPtr[kCCBlockSizeAES128 + 1];
memset(ivPtr, 0, sizeof(ivPtr));
[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [_data length];
int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
unsigned long int newSize = 0;
if(diff > 0)
{
newSize = 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 );
memset(buffer, 0, bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, 0x0000,
keyPtr, kCCKeySizeAES128,
ivPtr,
dataPtr,
sizeof(dataPtr),
buffer, bufferSize, /* output */
&numBytesEncrypted );
if( cryptStatus == kCCSuccess )
{
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free( buffer ); //free the buffer
return nil;
}
+ (NSData *)AES128DecryptWithKey:(NSString *)key withData:(NSData*)data iv:(NSString *) iv
{
char keyPtr[kCCKeySizeAES128 + 1];
memset(keyPtr, 0, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
char ivPtr[kCCBlockSizeAES128 + 1];
memset(ivPtr, 0, 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 numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, 0x0000,
keyPtr, kCCBlockSizeAES128,
ivPtr,
[data bytes],
dataLength,
buffer, bufferSize, /* output */
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer); //free the buffer;
return nil;
}
+ (NSString*) stringWithHexBytes:(NSData*)_data {
NSMutableString *stringBuffer = [NSMutableString stringWithCapacity:([_data length] * 2)];
const unsigned char *dataBuffer = [_data bytes];
int i;
for (i = 0; i < [_data length]; ++i) {
[stringBuffer appendFormat:@"%02lX", (unsigned long)dataBuffer[i]];
}
return [stringBuffer copy];
}
也是直接封裝在一個類裡面直接呼叫演算法就可以了,一般來說加密的時候專案你的開發文件上會告訴你這裡的金鑰你只要把相應的部分替換就可以了。
5.RSA待更新