iOS和Android的MD5校验一致性

作者: sz小泽 | 来源:发表于2016-11-17 15:53 被阅读1164次

MD5是使用哈希算法计算文件或字符串的摘要,将不定长的输入数据转化成128bit的数据,一般在使用的时候需要将它转换成十六进制输出,并且同时输出为小写,是不可还原出原始数据的(目前网站解密方式是采用撞库的方式,不是真正的解密)。
项目有个校验图片一致性的需要,用户上传图片到后台,后台根据一定的规则将图片数据转化成md5值返回给用户,当用户需要使用该图片时需要传入md5做一致性校验,防止用户修改图片。
字符串MD5的iOS代码如下:

-(NSString *)md5:(NSString *)str {
   const char *cStr = [str UTF8String];//转换成utf-8
   unsigned char result[16];//开辟一个16字节(128位:md5加密出来就是128位/bit)的空间(一个字节=8字位=8个二进制数)
   CC_MD5( cStr, strlen(cStr), result);
   /*
       extern unsigned char *CC_MD5(const void *data, CC_LONG len, unsigned char *md)官方封装好的加密方法
       把cStr字符串转换成了32位的16进制数列(这个过程不可逆转) 存储到了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]
           ];
   /*
       x表示十六进制,%02X  意思是不足两位将用0补齐,如果多余两位则不影响
       NSLog("%02X", 0x888);  //888
       NSLog("%02X", 0x4); //04
    */
}

也可以采用循环输出代码更简洁,采用官方提供的md5方法,输出固定长度128位的字符。
Androidd的md5校验代码如下:

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结果,但是将图片转成相应的字符串进行md5算法不一致了,原因是图片原始数据转化成字符串必须经过解码处理(转化成png或者jpg),Android和iOS不同的处理机制导致数据不一致,必须采用文件流的方式进行md5转化。
iOS文件流md5转化的相关代码

#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的相关代码如下:

 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();
    }

传入相关图片的路径,图片数据md5出来的数据一致,实现了md5校验的功能,使用md5校验时候要注意是字符串md5转化还是文件md5转化。

相关文章

  • iOS和Android的MD5校验一致性

    MD5是使用哈希算法计算文件或字符串的摘要,将不定长的输入数据转化成128bit的数据,一般在使用的时候需要将它转...

  • iOS中使用的MD5与Base64 (Objective-C)

    一. MD5 MD5数字校验NSString对象 MD5数字校验NSData对象 MD5数字加盐校验NSStrin...

  • mac sha校验文件 md5校验文件

    sha校验 md5校验

  • iOS Android DES加解密一致性问题

    iOS Android DES加解密一致性问题 iOS DES 加解密 Android DES加解密 iOS中支持...

  • ios和Android的大文件md5校验逻辑

    - 原因 保证服务器下发的资源在下载后没有修改,检测完整行 - ios代码 检验文件流 - Android文件流m...

  • 关于技术与产品的思考

    1.关于移动端对用户输入的校验 iOS和android的同事就移动端用户输入是否需要校验,以及用户输入是否需要更强...

  • 散列函数,sha1和md5

    信息摘要,数字签名,一致性对比。 什么是MD5,什么是SHA-1,如何校验这些Hash。还有拿单个ISO文件的MD...

  • Mac 小技巧

    MD5校验 终端输入md5加空格加需要校验的文件路径(也可以直接将需要校验的文件拖入终端窗口,相当于输入文件的目录...

  • 软件包的校验方法

    1. 用MD5进行校验 当你下载一个软件包后,你应该去校验它,如果你的软件包带有MD5校验码,你可用下面的方法进行...

  • Flutter-总结

    简介 谷歌开发的,有自己的渲染引擎,保持Android和iOS保持一致性渲染方式自己渲染。 MaterialApp...

网友评论

  • Roct:传入了 相册的路径 为什么获取不到MD5呢
    sz小泽:@Rocherster 我这个方法只是将字符串转化成md5值,你直接传入图片路径,当然获取不到md5,需要根据路径拿到图片数据再传进来
    Roct:@sz小泽 可以 都可以拿到 包括路径,路径是file:///,把获取到的路径传进去获取不到MD5,但是把图片写入沙盒 在用你的方法可以获取到.
    sz小泽:可以获取到图片数据吗
  • Mr_HeH:大牛,ios从手机拍得照片或者从相册选择的,路径填啥
    sz小泽:看你把照片存哪里,就选哪个路径
  • Ths:后台 php用原生的md5file 得到的值和iOS的不一样呢,不知道楼主你们后台用的是什么方法?
    eb04f7123b62:同问,楼主。 IOS这边是怎么处理的呢? 后台MD5加密文件与IOS前端加密不一致
    sz小泽:@Ths 数据md5还是字符串md5,这是不一样的,我当时也被坑了很久

本文标题:iOS和Android的MD5校验一致性

本文链接:https://www.haomeiwen.com/subject/dnurpttx.html