iOS和Android的MD5校驗(yàn)一致性

MD5是使用哈希算法計(jì)算文件或字符串的摘要蒸健,將不定長(zhǎng)的輸入數(shù)據(jù)轉(zhuǎn)化成128bit的數(shù)據(jù)衡创,一般在使用的時(shí)候需要將它轉(zhuǎn)換成十六進(jìn)制輸出,并且同時(shí)輸出為小寫(xiě)峡蟋,是不可還原出原始數(shù)據(jù)的(目前網(wǎng)站解密方式是采用撞庫(kù)的方式坟桅,不是真正的解密)。
項(xiàng)目有個(gè)校驗(yàn)圖片一致性的需要层亿,用戶(hù)上傳圖片到后臺(tái)桦卒,后臺(tái)根據(jù)一定的規(guī)則將圖片數(shù)據(jù)轉(zhuǎn)化成md5值返回給用戶(hù),當(dāng)用戶(hù)需要使用該圖片時(shí)需要傳入md5做一致性校驗(yàn)匿又,防止用戶(hù)修改圖片方灾。
字符串MD5的iOS代碼如下:

-(NSString *)md5:(NSString *)str {
   const char *cStr = [str UTF8String];//轉(zhuǎn)換成utf-8
   unsigned char result[16];//開(kāi)辟一個(gè)16字節(jié)(128位:md5加密出來(lái)就是128位/bit)的空間(一個(gè)字節(jié)=8字位=8個(gè)二進(jìn)制數(shù))
   CC_MD5( cStr, strlen(cStr), result);
   /*
       extern unsigned char *CC_MD5(const void *data, CC_LONG len, unsigned char *md)官方封裝好的加密方法
       把cStr字符串轉(zhuǎn)換成了32位的16進(jìn)制數(shù)列(這個(gè)過(guò)程不可逆轉(zhuǎn)) 存儲(chǔ)到了result這個(gè)空間中
    */
   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]
           ];
   /*
       x表示十六進(jìn)制,%02X  意思是不足兩位將用0補(bǔ)齊碌更,如果多余兩位則不影響
       NSLog("%02X", 0x888);  //888
       NSLog("%02X", 0x4); //04
    */
}

也可以采用循環(huán)輸出代碼更簡(jiǎn)潔裕偿,采用官方提供的md5方法,輸出固定長(zhǎng)度128位的字符痛单。
Androidd的md5校驗(yàn)代碼如下:

public static String stringToMD5(String string) {
        byte[] hash;
        try {
            hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10)
                hex.append("0");
            hex.append(Integer.toHexString(b & 0xFF));
        }
        return hex.toString().toLowerCase();
    }

輸入同樣的字符串可以得到相同的md5結(jié)果嘿棘,但是將圖片轉(zhuǎn)成相應(yīng)的字符串進(jìn)行md5算法不一致了,原因是圖片原始數(shù)據(jù)轉(zhuǎn)化成字符串必須經(jīng)過(guò)解碼處理(轉(zhuǎn)化成png或者jpg),Android和iOS不同的處理機(jī)制導(dǎo)致數(shù)據(jù)不一致旭绒,必須采用文件流的方式進(jìn)行md5轉(zhuǎn)化鸟妙。
iOS文件流md5轉(zhuǎn)化的相關(guān)代碼

#define FileHashDefaultChunkSizeForReadingData 1024*8
+(NSString*)getFileMD5WithPath:(NSString*)path
{
    return (__bridge_transfer NSString *)FileMD5HashCreateWithPath((__bridge CFStringRef)path, FileHashDefaultChunkSizeForReadingData);
}

CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath,size_t chunkSizeForReadingData) {
    // Declare needed variables
    CFStringRef result = NULL;
    CFReadStreamRef readStream = NULL;
    // Get the file URL
    CFURLRef fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
                                                     (CFStringRef)filePath,
                                                     kCFURLPOSIXPathStyle,
                                                     (Boolean)false);
    //    if (!fileURL) goto done;
    // Create and open the read stream
    readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault,
                                            (CFURLRef)fileURL);
    //    if (!readStream) goto done;
    bool didSucceed = (bool)CFReadStreamOpen(readStream);
    //    if (!didSucceed) goto done;
    // Initialize the hash object
    CC_MD5_CTX hashObject;
    CC_MD5_Init(&hashObject);
    // Make sure chunkSizeForReadingData is valid
    if (!chunkSizeForReadingData) {
        chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData;
    }
    // Feed the data to the hash object
    bool hasMoreData = true;
    while (hasMoreData) {
        uint8_t buffer[chunkSizeForReadingData];
        CFIndex readBytesCount = CFReadStreamRead(readStream,(UInt8 *)buffer,(CFIndex)sizeof(buffer));
        if (readBytesCount == -1) break;
        if (readBytesCount == 0) {
            hasMoreData = false;
            continue;
        }
        CC_MD5_Update(&hashObject,(const void *)buffer,(CC_LONG)readBytesCount);
    }
    // Check if the read operation succeeded
    didSucceed = !hasMoreData;
    // Compute the hash digest
    unsigned char digest[CC_MD5_DIGEST_LENGTH];
    CC_MD5_Final(digest, &hashObject);
    // Abort if the read operation failed
    if (!didSucceed) goto done;
    // Compute the string result
    char hash[2 * sizeof(digest) + 1];
    for (size_t i = 0; i < sizeof(digest); ++i) {
        snprintf(hash + (2 * i), 3, "%02x", (int)(digest[i]));
    }
    result = CFStringCreateWithCString(kCFAllocatorDefault,(const char *)hash,kCFStringEncodingUTF8);
done:
    if (readStream) {
        CFReadStreamClose(readStream);
        CFRelease(readStream);
    }
    if (fileURL) {
        CFRelease(fileURL);
    }
    return result;
}

Android文件流md5的相關(guān)代碼如下:

 public static String getMD5(String imagePath) throws NoSuchAlgorithmException, IOException {

        InputStream in = new FileInputStream(new File(imagePath));

        StringBuffer md5 = new StringBuffer();
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] dataBytes = new byte[1024];

        int nread = 0;
        while ((nread = in.read(dataBytes)) != -1) {
            md.update(dataBytes, 0, nread);
        }

        byte[] mdbytes = md.digest();

        // convert the byte to hex format
        for (int i = 0; i < mdbytes.length; i++) {
            md5.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
        }
        return md5.toString().toLowerCase();
    }

傳入相關(guān)圖片的路徑,圖片數(shù)據(jù)md5出來(lái)的數(shù)據(jù)一致挥吵,實(shí)現(xiàn)了md5校驗(yàn)的功能重父,使用md5校驗(yàn)時(shí)候要注意是字符串md5轉(zhuǎn)化還是文件md5轉(zhuǎn)化。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末忽匈,一起剝皮案震驚了整個(gè)濱河市房午,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丹允,老刑警劉巖郭厌,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異雕蔽,居然都是意外死亡折柠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)萎羔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)液走,“玉大人,你說(shuō)我怎么就攤上這事≡悼簦” “怎么了嘱根?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)巷懈。 經(jīng)常有香客問(wèn)我该抒,道長(zhǎng),這世上最難降的妖魔是什么顶燕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任凑保,我火速辦了婚禮,結(jié)果婚禮上涌攻,老公的妹妹穿的比我還像新娘欧引。我一直安慰自己,他們只是感情好恳谎,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布芝此。 她就那樣靜靜地躺著,像睡著了一般因痛。 火紅的嫁衣襯著肌膚如雪婚苹。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,268評(píng)論 1 309
  • 那天鸵膏,我揣著相機(jī)與錄音膊升,去河邊找鬼。 笑死谭企,一個(gè)胖子當(dāng)著我的面吹牛廓译,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播债查,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼责循,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了攀操?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤秸抚,失蹤者是張志新(化名)和其女友劉穎速和,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體剥汤,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡颠放,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吭敢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碰凶。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出欲低,到底是詐尸還是另有隱情辕宏,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布砾莱,位于F島的核電站瑞筐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏腊瑟。R本人自食惡果不足惜聚假,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闰非。 院中可真熱鬧膘格,春花似錦、人聲如沸财松。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)游岳。三九已至政敢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胚迫,已是汗流浹背喷户。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留访锻,地道東北人褪尝。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像期犬,于是被迫代替她去往敵國(guó)和親河哑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容