用CommonCrypto計算MD5和SHA


感謝作者:http://www.keakon.net/2011/08/13/用CommonCrypto計算MD5和SHA

編程時經常需要和MD5、SHA等hash算法打交道,搜了一下后我發現iOS SDK中自帶了CommonCrypto,於是就無需自己實現或用第三方庫了。

首先來看MD5,它的輸出結果是128位的,因此需要16個8位的char來存儲。而輸入參數我就直接用const char *了,反正NSString和NSData都能與它相互轉換:

#include <CommonCrypto/CommonDigest.h>

static inline char hexChar(unsigned char c) {
    return c < 10 ? '0' + c : 'a' + c - 10;
}

static inline void hexString(unsigned char *from, char *to, NSUInteger length) {
    for (NSUInteger i = 0; i < length; ++i) {
        unsigned char c = from[i];
        unsigned char cHigh = c >> 4;
        unsigned char cLow = c & 0xf;
        to[2 * i] = hexChar(cHigh);
        to[2 * i + 1] = hexChar(cLow);
    }
    to[2 * length] = '\0';
}

NSString * md5(const char *string) {
    static const NSUInteger LENGTH = 16;
    unsigned char result[LENGTH];
    CC_MD5(string, (CC_LONG)strlen(string), result);
    
    char hexResult[2 * LENGTH + 1];
    hexString(result, hexResult, LENGTH);
    
    return [NSString stringWithUTF8String:hexResult];
}

NSLog(@"%@", md5("test"));

這里首先是調用CC_MD5()來計算,不過它的計算結果是字符數組,而一般我們是使用16進制格式的字符串。
因此只好再創建一個字符串,長度為33位(以'\0'結尾),再分別取每個字符的高16位和低16位來轉化成16進制。算法也很簡單,0~9直接加上'0',a~f則減10后加上'a'。
接着發現debug模式下不能直接使用inline函數,於是只好加上static修飾。
不怕辛苦的也可以用NSString的stringWithFormat:方法來構造,不過要寫17個參數也很累,而且不知道效率如何。

接下來再來看SHA。CommonCrypto支持計算SHA1、SHA224、SHA256、SHA384和SHA512,考慮到目前SHA1已足夠安全了,於是就以它為例。
和MD5不同的是,它的輸出結果是160位的,所以需要20個8位的char來存儲:

NSString * sha1(const char *string) {
    static const NSUInteger LENGTH = 20;
    unsigned char result[LENGTH];
    CC_SHA1(string, (CC_LONG)strlen(string), result);
    
    char hexResult[2 * LENGTH + 1];
    hexString(result, hexResult, LENGTH);
    
    return [NSString stringWithUTF8String:hexResult];
}

NSLog(@"%@", sha1("test"));

邏輯幾乎是一樣的,所以就不再解釋了。
不過既然代碼都差不多,自然可以更進一步,做個更通用的hash函數,直接根據傳入的算法名來運行不同的算法。只是我懶得去做了,因為我用不到~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM