md5和SHA校验码

md5已经不安全了,中国山东大学女学霸王小云破解了一系列密码,当真是巾帼不让须眉.说是破解,其实就是给你一个md5码,让你求出这个md5码所对应的原始信息,显然一个md5对应无数种原始信息.而md5的特性就是难以还原初始信息,但是王小云可以迅速找到给定md5码的可行解.md5的解空间虽然巨大,但是却难以捕捉到解.

md5虽然已经不安全了,但是仍然可以用于校验.

md5不是编码,编码是能够还原初始信息的,而md5只是固定的16byte,它只能从总体上反映初始信息的一些特征,却无法完整的还原出来,因为初始信息到md5码是一个多对一映射.

md5中大量使用小头序,这点十分坑.还好java中有神奇伟大的ByteBuffer.ByteBuffer有四个索引:mark,limit,position,capacity.

mark表示标记;limit表示position最大可以读到哪里;position表示当前位置;capacity表示最大容量.

ByteBuffer这个类支持"流式"编程,比如put(byte)函数返回值仍然是ByteBuffer,这样就可以接着put了.

ByteBuffer这个类最重要的就是4个指针,玩转了四个指针就学会了控制ByteBuffer,例如:

flip()将limit置为当前position,将position置为0,准备从头读取数据,注意只能读取0~limit这一部分数据;

rewind()将position置为0;

mark()标记当前position,可以使用reset()将position重置为mark时的位置.

compact()将当前postion之前的字节清空.

clear()清空一切,将limit移动到copacity处,准备读入数据.

明白了如何操作这些指针,就明白了ByteBuffer.

当不了解md5的时候,听人们说md5的某些特性,觉得还是道听途说,只有亲自实现之后才能自己总结出md5有哪些特点.

下面给出md5信息摘要算法

import static java.lang.Math.abs;
import static java.lang.Math.floor;
import static java.lang.Math.pow;
import static java.lang.Math.sin;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5 {
    // 移位的位数,分成4种,每种4个数,每种重复4次.不知道为啥是这些数字
    int[] s = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9,
            14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4,
            11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15,
            21, 6, 10, 15, 21, 6, 10, 15, 21};
    // 在init函数中初始化k[i]
    int k[] = new int[64];
    void init() {
        for (int i = 0; i < 64; i++) {
            long x = (long) floor(abs(sin(i + 1)) * pow(2, 32));
            k[i] = (int) (x & 0xffffffff);
        }
    }
    // 循环左移操作,比如4位的1011,循环左移一位相当于0110|1
    int leftRotate(int x, int n) {
        return (x << n) | (x >>> (32 - n));
    }
    byte[] digest(byte[] srcData) throws IOException {
        // 原数据字节数+8byte的原始长度表示=l,l有点偏短,如果它不是64的倍数,那么会舍弃一些,所以要加上一;如果它是64的倍数,那么需要补上一个字节,至少要添加一个chunk.
        // 一个chunk为64byte,其中最后一个chunk的前56byte为数据+补齐的数据,最后8byte为long类型的数据,表示原始数据长度.
        // 整个md5都是基于小头序的
        int chunkCount = (srcData.length + 8) / 64 + 1;
        ByteBuffer buffer = ByteBuffer.allocate(chunkCount * 64)
                .order(ByteOrder.LITTLE_ENDIAN);
        buffer.put(srcData).put((byte) 0x80).position(buffer.limit() - 8);
        buffer.putLong(8 * srcData.length).flip();//flip准备读取数据
        int a0 = 0x67452301, b0 = 0xefcdab89, c0 = 0x98badcfe, d0 = 0x10325476;
        while (buffer.hasRemaining()) {
            int m[] = new int[16];
            for (int i = 0; i < 16; i++) {
                m[i] = buffer.getInt();
            }
            int a = a0, b = b0, c = c0, d = d0;
            int f, g;
            for (int i = 0; i < 64; i++) {
                if (i < 16) {
                    f = (b & c) | (~b & d);
                    g = i;
                } else if (i < 32) {
                    f = (d & b) | (~d & c);
                    g = (5 * i + 1) % 16;
                } else if (i < 48) {
                    f = b ^ c ^ d;
                    g = (3 * i + 5) % 16;
                } else {
                    f = c ^ (b | ~d);
                    g = (7 * i) % 16;
                }
                int dd = d;
                d = c;
                c = b;
                b = b + leftRotate(a + f + k[i] + m[g], s[i]);
                a = dd;
            }
            a0 += a;
            b0 += b;
            c0 += c;
            d0 += d;
        }
        return ByteBuffer.allocate(16).order(ByteOrder.LITTLE_ENDIAN).putInt(a0)
                .putInt(b0).putInt(c0).putInt(d0).array();
    }
    static void show(byte[] b) {
        for (byte i : b) {
            System.out.printf("%02X", i);
        }
        System.out.println();
    }
    public static void main(String[] args)
            throws NoSuchAlgorithmException, IOException {
        byte[] b = "魏印福".getBytes();
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        md5.update(b);
        byte[] res = md5.digest();
        show(res);
        MD5 m = new MD5();
        m.init();
        res = m.digest(b);
        show(res);
    }
}

跟md5一样,SHA也有好多版本,SHA1,SHA2,SHA3,其中SHA2,SHA3又分成了好多版本.SHA加密强度比md5更强,它名叫Secure Hash Algorithm.md5校验码位长相当于4个int,SHA的位长相当于5个int.二者都是以64Byte为一个chunk进行处理.

下面给出java中如何使用库函数自带的SHA

public class SHA {
    static String tos(byte[] b) {
        String ans = "";
        for (int i = 0; i < b.length; i++) {
            ans += String.format("%02X", b[i]);
        }
        return ans;
    }
    public static void main(String[] args) throws Exception {
        byte[] data = "魏印福".getBytes();
        MessageDigest digest = MessageDigest.getInstance("SHA");
        byte[] ans = digest.digest(data);
        System.out.println(tos(ans));
        System.out
                .println(tos(MessageDigest.getInstance("SHA-1").digest(data)));
    }
}
时间: 2024-10-24 09:09:36

md5和SHA校验码的相关文章

MD5、SHA校验命令

linux系统的软件很多时候都以境像的方式提供下载,但我们如何确实下载的文件是没有被篡改过的呢?Linux中一般用对下载的文件进行MD5和SHA校验来确认. MD5 我们拿iptraf软件来试验: 我们可以看到,官方已经提供了md5值,我们需要做的就是对下载下来的tar.gz文件运行md5sum命令,看运算出来的md5sum值与官方给的是不是一致. 命令: $ md5sum iptraf-3.0.0.tar.gz 结果: 377371c28ee3c21a76f7024920649ea8 iptr

Android MD5校验码的生成与算法实现

在Java中,java.security.MessageDigest (rt.jar中)已经定义了 MD5 的计算,所以我们只需要简单地调用即可得到 MD5 的128 位整数.然后将此 128 位计 16 个字节转换成 16 进制表示即可. 下面是一个可生成字符串或文件MD5校验码的例子,测试过,可当做工具类直接使用,其中最主要的是getMD5String(String s)和getFileMD5String(File file)两个方法,分别用于生成字符串的md5校验值和生成文件的md5校验值

Java 获取 文件md5校验码

讯雷下载的核心思想是校验文件的md5值,两个文件若md5相同则为同一文件. 当得到用户下载某个文件的请求后它根据数据库中保留的文件md5比对出拥有此文件的url, 将用户请求挂接到此url上并仿造一个虚假的断点续传请求,从若干url上将一个正常文件拼接出来. 查了下资料,java也可以实现文件md5校验码获取,代码如下: import java.io.File;import java.io.FileInputStream;import java.io.IOException;import jav

java生成MD5校验码

在Java中,java.security.MessageDigest (rt.jar中)已经定义了 MD5 的计算,所以我们只需要简单地调用即可得到 MD5 的128 位整数.然后将此 128 位计 16 个字节转换成 16 进制表示即可. 下面是一个可生成字符串或文件MD5校验码的例子,测试过,可当做工具类直接使用,其中最主要的是getMD5String(String s)和getFileMD5String(File file)两个方法,分别用于生成字符串的md5校验值和生成文件的md5校验值

C# 获取文件MD5校验码

using System; using System.IO; using System.Security.Cryptography; using System.Text; public class MD5Code { /// <summary> /// Get 文件的MD5校验码 /// </summary> /// <param name="fileName">文件名称</param> /// <returns></r

BASE64、MD5、SHA、HMAC几种加密算法

本篇内容简要介绍BASE64.MD5.SHA.HMAC几种加密算法.    BASE64编码算法不算是真正的加密算法.    MD5.SHA.HMAC这三种加密算法,可谓是非可逆加密,就是不可解密的加密方法,我们称之为单向加密算法.我们通常只把他们作为加密的基础.单纯的以上三种的加密并不可靠. BASE64 按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式.(The Base64 Content-Transfe

支持APP手机应用(android和ios)接口调用 ,传输验证可用 shiro 的 MD5、SHA 等加密

请认准本正版代码,售后技术有保障,代码有持续更新.(盗版可耻,违者必究)         此为本公司团队开发 ------------------------------------------------------------------------------------------------------------------------- 1. 有 oracle .msyql.spring3.0.spring4.0  一共 4 套版本全部提供没有打jar没有加密的源代码(最下面截图2

C# 计算字符串的哈希值(MD5、SHA)

一.关于本文 本文中是一个类库,包括下面几个函数: 1)计算32位MD5码(大小写):Hash_MD5_32 2)计算16位MD5码(大小写):Hash_MD5_16 3)计算32位2重MD5码(大小写):Hash_2_MD5_32 4)计算16位2重MD5码(大小写):Hash_2_MD5_16 5)计算SHA-1码(大小写):Hash_SHA_1 6)计算SHA-256码(大小写):Hash_SHA_256 7)计算SHA-384码(大小写):Hash_SHA_384 8)计算SHA-512

常用加密算法的Java实现(一)——单向加密算法MD5和SHA

1.Java的安全体系架构 1.1           Java的安全体系架构介绍 Java中为安全框架提供类和接口.JDK 安全 API 是 Java 编程语言的核心 API,位于 java.security包(及其子包),以及sun.securityAPI包(及其子包)中.设计用于帮助开发人员在程序中同时使用低级和高级安全功能. JDK 1.1 中第一次发布的 JDK 安全中引入了“Java 加密体系结构”(JCA),指的是用于访问和开发 Java平台密码功能的构架.在 JDK 1.1 中,