MD5 与 Base64一起使用 加密,计算原理

目录

■加密效果(MD5 + Base64)

■如何计算

相关知识

1.负数二进制表示

2.base64编码表

■加密代码 MD5 + Base64

2021/09/06  追记1 問題 :MD5不是16进制文本

追记1问题   (2022/05/06)解决 :可以转换为16进制文本

■ 计算文件哈希值的的代码 (自定义)

■生成文件的MD5值 (代码完全正确)

代码 (使用ERMaster的Jar作为示例)

代码运行结果

 PowerShell生成的MD5  (完全相同)


加密效果(MD5 + Base64)

加密原文:

1234

加密后的结果:

gdyb21LQTcIANtvYMT7QVQ==

22位(不包括等于号)

123456

4QrcOUm6Wau+VuBX8g+IPg==

■如何计算

1.使用MD5,取得信息摘要

1234对应的信息摘要如下

[-127, -36, -101, -37, 82, -48, 77, -62, 0, 54, -37, -40, 49, 62, -48, 85]

一共 16 byte

16*8=128

128%6=2

21余2

2.使用Base64再次处理

  1.将每三个字节分成一组,一共24个二进制位:3*8=24

  2.将这24个二进制位分成4组,每组有6个二进制位:24/4=6

  3.在每组前加两00,扩展成32个二进制位,即4个字节:4*(6+2)=32

  4.根据下面的编码表,得到扩展后每个字节的对应符号,就是Base64的编码值

注意:

  1.因为转换后的每个字符的最高两位都是0,所以实际有效位数是6位,

     也就是26=64个字符就可以覆盖所有的编码。

  2.如果剩下的字符不足3个字节,则用0填充,输出字符使用"=",

     因此编码后输出的文本末尾可能会出现1或2个"="。

  3.因为Base64将3个字节转化成4个字节,因此Base64编码后的文本,

     会比原文本大出三分之一左右。

补=的规律:

(如果N*8%6后余2个二进制位,就补2个=,余4个二进制位就补一个=,整除不补)

剩余两位 ,2*8=16 % 6 结果为(余数为) 4

剩余一位,1*8=8   %6  结果为(余数为) 2

前三位对应的二进制(正数的补码)

-127
10000001
-36
11011100
-101
10011011

转化为四个字符(3*8bit=4*6bit)
100000 ⇒32 ⇒g
011101 ⇒29 ⇒d
110010 ⇒50 ⇒y
011011 ⇒27 ⇒b

补充说明

MD5是一种信息摘要算法,并不是加密算法

相关知识

1.负数二进制表示

正数对应的反码

反码加1,取得补码

补码就是负数的二进制表示

2.base64编码表

索引
对应字符
索引
对应字符
索引
对应字符
索引
对应字符
0
A
17
R
34
i
51
z
1
B
18
S
35
j
52
0
2
C
19
T
36
k
53
1
3
D
20
U
37
l
54
2
4
E
21
V
38
m
55
3
5
F
22
W
39
n
56
4
6
G
23
X
40
o
57
5
7
H
24
Y
41
p
58
6
8
I
25
Z
42
q
59
7
9
J
26
a
43
r
60
8
10
K
27
b
44
s
61
9
11
L
28
c
45
t
62
+
12
M
29
d
46
u
63
/
13
N
30
e
47
v
14
O
31
f
48
w
15
P
32
g
49
x
16
Q
33
h
50
y


加密代码 MD5 + Base64

package com.ams.lms.util;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import sun.misc.BASE64Encoder;

@SuppressWarnings("restriction")
public class MD5Util {

	/**
	 * 利用MD5进行加密
	 * 
	 * @param str
	 *            待加密的字符串
	 * @return 加密后的字符串
	 * @throws NoSuchAlgorithmException
	 * @throws UnsupportedEncodingException
	 */
	public static String EncoderByMd5(String str) {
		if (str == null) {
			return null;
		}
		try {
			// 确定计算方法
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			BASE64Encoder base64en = new BASE64Encoder();
			// 加密后的字符串
			return base64en.encode(md5.digest(str.getBytes("utf-8")));
		} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
			return null;
		}
	}
}


2021/09/06  追记1 問題 :MD5不是16进制文本

为什么要先MD5,再用Base64进行加密

使用Java生成的MD5的值,和我们期待的不太一样,并不是十六进制组成的文本。

有特殊字符,造成无法正常的网络传输。


MD5 与 Base64一起使用 加密,计算原理_第1张图片

===

追记1问题   (2022/05/06)解决 :可以转换为16进制文本

---

package com.sxz.common.utils;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class GetMD5Info {
	
	public static void main (String[] args) {
		
		System.out.println(EncoderByMd5("123"));		
		
	}
	
	public static String EncoderByMd5(String str) {
		if (str == null) {
			return null;
		}
		
		String strMD5 = "";
		
		
		try {
			// 确定计算方法
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			// 加密后的字符串
			byte[] bytes = md5.digest(str.getBytes("utf-8"));
			
			strMD5 = String.format("%032x", new BigInteger(1, bytes));
			
		} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
			return null;
		}

		
		return strMD5;
	}
	
}

---

得到的结果是

202cb962ac59075b964b07152d234b70

---

 计算文件哈希值的的代码 (自定义)

===

import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.FileInputStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;

@Slf4j
public class SHA1 {

    protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E','F' };

    /**
     * @Description: 计算SHA1码
     * @Param file
     * @Return java.lang.String
     * @Author Menglong.Cao
     * @Date 2022/3/1 16:43
     */
    public static String generate(File file){
        try{
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
            FileInputStream in = new FileInputStream(file);
            FileChannel ch = in.getChannel();
            MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY,0,file.length());
            messageDigest.update(byteBuffer);
            return bufferToHex(messageDigest.digest());
        }catch (Exception e){
            log.warn("generate-hash-fail:errorMessage={},{}",e.getMessage(),e);
        }
        return null;

    }

    private static String bufferToHex(byte bytes[]){
        return bufferToHex(bytes,0,bytes.length);
    }

    private static String bufferToHex(byte bytes[],int m,int n){
        StringBuffer stringBuffer = new StringBuffer(2*n);
        int k = m + n;
        for(int l = m; l < k; l++){
            appendHexPair(bytes[l],stringBuffer);
        }
        return stringBuffer.toString();
    }

    private static void appendHexPair(byte bt, StringBuffer stringBuffer){
        char c0 = hexDigits[(bt & 0xf0) >> 4];
        char c1 = hexDigits[bt & 0xf];
        stringBuffer.append(c0);
        stringBuffer.append(c1);
    }

    //测试
    public static void main(String[] args) throws Exception{
        System.out.println("begin...");
        long begin = System.currentTimeMillis();
        File file2 = new File("D:\\计算hash.txt");
        String sha1 = SHA1.generate(file2);
        System.out.println("文件hash:"+sha1);// 82C189E0D231901FFC0597401F75CB54F44331A8
        System.out.println("耗时:"+(System.currentTimeMillis()-begin)+"ms");
        System.out.println("end...");
    }

}

----

■生成文件的MD5值 (代码完全正确)

代码 (使用ERMaster的Jar作为示例)

package com.sxz.study.algorithm;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class TestMD5File {

	public static void main(String[] args) {
		
		
		String md5str = getMD5Three("C:\\eclipse\\下载的plugin\\ERMaster\\org.insightech.er_1.0.0.v20150619-0219.jar");
		System.out.println(md5str);

	}
	
	public static String getMD5Three(String path) {
	     BigInteger bi = null;
	      try {
	          byte[] buffer = new byte[8192];
	          int len = 0;
	          MessageDigest md = MessageDigest.getInstance("MD5");
	          File f = new File(path);
	          FileInputStream fis = new FileInputStream(f);
	          while ((len = fis.read(buffer)) != -1) {
	             md.update(buffer, 0, len);
	          }
	             fis.close();
	             byte[] b = md.digest();
	             bi = new BigInteger(1, b);
	      } catch (NoSuchAlgorithmException e) {
	            e.printStackTrace();
	      } catch (IOException e) {
	             e.printStackTrace();
	         }
	         

            // 下面代码有BUG,当MD5的Hash值,第一位是0是,第一位会被省略。
            // return bi.toString(16);

            // 使用下面代码解决bug (MD5的值,是一个32位长度的字符串)
            String md5Str = bi.toString(16);
            String md5StrFormat = md5Str.format("%32s", mdtStr); // 不足32位,前面补空格
            String result= md5StrFormat.replace(" ", "0"); // 把空格替换成0

            String result.toUpperCase();
            
	     }
	

}

代码运行结果

 PowerShell生成的MD5  (完全相同)

Get-FileHash -Algorithm MD5 .\org.insightech.er_1.0.0.v20150619-0219.jar | Format-list

MD5 与 Base64一起使用 加密,计算原理_第2张图片

==

你可能感兴趣的:(算法,人工智能,算法)