使用jdk提供的MessageDigest类实现md5加密

MD5介绍

MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。广泛用于加密和解密技术,

MD5加密属于单向加密,可以从明文转化为密文,但是无法从密文转为明文

JDK提供的MD5实现使用步骤

  1. 通过protected MessageDigest(String algorithm)方法。根据根据指定的算法名称来获取MessageDigest对象
  2. 使用MessageDigest对象的public void update(byte[] input)方法,用指定的字节数组更新摘要
  3. 使用MessageDigest对象对象的public byte[] digest()方法,用通过执行最后的操作(如填充)来完成哈希计算。 此通话完成后,摘要将重置。用于生成的哈希值的字节数组。 也就是加密后的数组
  4. 使用BigInteger包装类将加密后的数组转化为十进制的数字,因为int和integer都无法直接将数组转化为十进制的数字
  5. 然后将十进制数转化为十六进制数

举例示范

//要加密的数字
        String source = "123123";
        // 3、获取MessageDigest对象
        String algorithm = "md5";
        MessageDigest messageDigest = null;
        try {
            //通过MessageDigest类来的静态方法getInstance获取MessageDigest对象
            messageDigest = MessageDigest.getInstance(algorithm);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        // 4、获取明文字符串对应的字节数组
        byte[] input = source.getBytes();
        // 5、执行加密
         messageDigest.update(input);
         //这里也可以直接使用byte[] output = messageDigest.digest(input)方法来进行加密,就省略了上面的update方法了
        byte[] output = messageDigest.digest();
        // 6、创建BigInteger对象
        // signum为1表示正数、-1表示负数、0表示0。不写默认表示正数
        int signum = 1;
        BigInteger bigInteger = new BigInteger(signum,output);
        // 7、按照十六进制将bigInteger转为字符串
        int radix = 16;
        String encoded = bigInteger.toString(radix).toUpperCase();
        System.out.println(encoded);

疑问

为什么加密后的bytes字节数组要转化为十六进制再转化为字符串

在加密时,一般加密算法和hash算法,它们操作的都是字节数组,对字节数组按照加密算法进行各种变换,运算,得到的结果也是字节数组。
而我们一般是要求对字符串进行加密,所以就涉及到字符串String到 byte[] 的转换,这个很简单,就是直接字符串.getBytes就能获得String对应的byte[]
并且因为最终加密后的数据需要保存到数据库中,所以加密得到 byte[] 也要转换到 String.

String 到 byte[] 的转换很简单,因为String类有直接的函数。
但是,byte[] 到String 的转换却没有那么简单其原因是,我们不能简单的使用使用String的函数:也就是不能使用 new String(byte); 也不能使用 new String(byte, charset),着是为什么呢?
很简单因为, md5, SHA-256, SHA-512 等等算法,它们是通过对byte[] 进行各种变换和运算,得到加密之后的byte[],那么这个加密之后的 byte[] 结果显然 就不会符合任何一种的编码方案,比如 utf-8, GBK等,因为加密的过程是任意对byte[]进行运算的。所以你用任何一种编码方案来解码,加密之后的 byte[] 结果,得到的都会是乱码。

而且因为我们选择的是使用BigIntgeger来讲字节数组转为十进制的数字,然后再转为字符串的,如果不将这个bigInteger转为16进制那么它所占的位数会太长,不利于存储

posted @ 2021-03-27 20:24  谢海川  阅读(405)  评论(0)    收藏  举报