1. md5:
MD5即Message-Digest Algorithm 5(資訊-摘要演算法5),用於確保資訊傳輸完整一致。是電腦廣泛使用的雜湊演算法之一(又譯摘要演算法、雜湊演算法),主流程式設計語言普遍已有MD5實現。MD5的作用是讓大容量資訊在用數位簽章軟體簽署私人密鑰前被"壓縮"成一種保密的格式(就是把一個任意長度的位元組串變換成一定長的十六進位數字串)。(引用自百度百科)
MD5加密目前來說是無法復原的,只能用作一些檢驗過程,不能恢複其原文。
MD5演算法產生的是固定的128bit,即128個0和1的二進位位,而在實際應用開發中,通常是以16進位輸出的,所以正好就是32位的16進位數,說白了也就是32個16進位的數字。
需要引入標頭檔:
#import <CommonCrypto/CommonDigest.h>
#define CC_MD5_DIGEST_LENGTH 16 /* digest length in bytes */
- (NSString *)md5:(NSDictionary *)paramsDict {NSString *inString = [paramsDict stringValueForKey:@"data" defaultValue:@""]; if (inString.length <= 0) { return @""; } else { const char *cStrValue = [inString UTF8String]; //開闢一個16位元組(128位:md5加密出來就是128位/bit)的空間(一個位元組=8字位=8個位元) unsigned char outResult[CC_MD5_DIGEST_LENGTH]; CC_MD5(cStrValue, strlen(cStrValue), outResult); //x表示十六進位,X 意思是不足兩位將用0補齊,如果多餘兩位則不影響 NSString *outString = [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", outResult[0], outResult[1], outResult[2], outResult[3], outResult[4], outResult[5], outResult[6], outResult[7], outResult[8], outResult[9], outResult[10], outResult[11], outResult[12], outResult[13], outResult[14], outResult[15]]; /* //方法二: NSMutableString *outString = [NSMutableString string]; for (int i = 0; i < 16; i++) { [outString appendFormat:@"X", outResult[i]]; } */ return outString; } }
為什麼是[16]呢,這是因為MD5演算法最後產生的是128位,而在電腦的最小儲存單位為位元組,1個位元組是8位,對應一個char類型,計算可得需要16個char。所以result是[16]。那麼為什麼輸出的格式一定是%02x呢,而不是其它呢。這也是有原因的:因為約定MD5一般是以16進位的格式輸出,那麼其實這個問題就轉換為把128個0和1以16進位來表示,每4位二進位對應一個16進位的元素,則需要32個16進位的元素,如果元素全部為0,放到char的數組中,正常是不會輸出,如00001111,以%x輸出,則是f,那麼就會丟失0;但如果以%02x表示則輸出結果是0f,正好是轉換的正確結果。
2. sha1 加密
SHA1 演算法一樣無法復原。
- (NSString *) sha1:(NSString *)input{ const char *cstr = [input cStringUsingEncoding:NSUTF8StringEncoding]; NSData *data = [NSData dataWithBytes:cstr length:input.length]; //#define CC_SHA1_DIGEST_LENGTH 20 /* digest length in bytes */ uint8_t digest[CC_SHA1_DIGEST_LENGTH]; CC_SHA1(data.bytes, data.length, digest); NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2]; for(int i=0; i<CC_SHA1_DIGEST_LENGTH; i++) { [output appendFormat:@"%02x", digest[i]]; } return output;}
3. AES 加密
進階加密標準(Advanced Encryption Standard,AES),又稱Rijndael加密法。
需要注意的是,AES並不能作為HASH演算法,加密並解密後的結果,並不一定與原文相同,使用時請注意進行結果驗算。例如解密原文的長度,格式規則等。
需要引入標頭檔
#import <CommonCrypto/CommonCryptor.h>
加密和解密方法使用的參數密鑰可以均為32位長度的字串,可以將任意的字串經過md5計算32位字串作為密鑰,也可以自訂如:
#define APP_PUBLIC_PASSWORD @"boundary"
- (NSData *)AES256EncryptWithKey:(NSString *)key withString:(NSString *) inputString { //加密 NSData *inData = [inString dataUsingEncoding:NSUTF8StringEncoding]; /*** //如果希望返回字串,在開始時就開始對 NSData 做轉換, 對應下面方法三,方法一和二使用上面語句即可 const char *cstr = [inString cStringUsingEncoding:NSUTF8StringEncoding]; NSData *inData = [NSData dataWithBytes:cstr length:inString.length]; ***/ char keyPtr[kCCKeySizeAES256+1]; bzero(keyPtr, sizeof(keyPtr)); [APP_PUBLIC_PASSWORD getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [inData length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [inData bytes], dataLength, buffer, bufferSize, &numBytesEncrypted); if (cryptStatus == kCCSuccess) { NSData *outData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; return outData; /*** //如果需要返回 NSString 類型的結果,這裡需要進行轉換: // 方法一: NSString *outString = [[NSString alloc]initWithData:outData encoding:NSUTF8StringEncoding]; //失敗,注意:這裡 outString 為 nil,具體原因貌似是因為 NSData 內容含有非encoding編碼的字元 // 方法二: NSString *outString = [outData base64Encoding]; // 方法三:(轉換為2進位字串) if (outData && outData.length > 0) { Byte *datas = (Byte*)[outData bytes]; NSMutableString *outString = [NSMutableString stringWithCapacity:outData.length * 2]; for(int i = 0; i < outData.length; i++){ [outString appendFormat:@"%02x", datas[i]]; } } ***/ } free(buffer); return nil;}
//解密可以直接使用加密得到的結果 NSData, 這樣將很容易,不必進行字元轉換- (NSData *)AES256DecryptWithKey:(NSString *)key withNSData:(NSString *)inData {//解密/***- (NSData *)AES256DecryptWithKey:(NSString *)key withString:(NSString *)inputString {//解密 //對應密碼編譯演算法中的方法二:(解密前進行GTMBase64編碼) NSData *inData = [GTMBase64 decodeString:inString]; //對應密碼編譯演算法中的方法三: NSMutableData *inData = [NSMutableData dataWithCapacity:inString.length / 2]; unsigned char whole_byte; char byte_chars[3] = {'\0','\0','\0'}; int i; for (i=0; i < [inString length] / 2; i++) { byte_chars[0] = [inString characterAtIndex:i*2]; byte_chars[1] = [inString characterAtIndex:i*2+1]; whole_byte = strtol(byte_chars, NULL, 16); [inData appendBytes:&whole_byte length:1]; } ***/ char keyPtr[kCCKeySizeAES256+1]; bzero(keyPtr, sizeof(keyPtr)); //使用 "key": #define APP_PUBLIC_PASSWORD @"boundary" [APP_PUBLIC_PASSWORD getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [inData length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesDecrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [inData bytes], dataLength, buffer, bufferSize, &numBytesDecrypted); if (cryptStatus == kCCSuccess) { NSData *outData = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; return outData; /*** //若需返回 NSString,需要上面密碼編譯演算法和解密演算法的各個方法對應好,使用下列語句才不會返回 nil; 切記 dataLength 一定匹配好 NSString *outString = [[NSString alloc]initWithData:outData encoding:NSUTF8StringEncoding]; ***/ } free(buffer); return nil;}
4. base 64 密碼編譯演算法
下載庫 GTMBase64
執行個體demo: http://up.2cto.com/2012/1215/20121215123257741.zip