当前位置:   article > 正文

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

md5和base64

加密效果(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

  1. package com.ams.lms.util;
  2. import java.io.UnsupportedEncodingException;
  3. import java.security.MessageDigest;
  4. import java.security.NoSuchAlgorithmException;
  5. import sun.misc.BASE64Encoder;
  6. @SuppressWarnings("restriction")
  7. public class MD5Util {
  8. /**
  9. * 利用MD5进行加密
  10. *
  11. * @param str
  12. * 待加密的字符串
  13. * @return 加密后的字符串
  14. * @throws NoSuchAlgorithmException
  15. * @throws UnsupportedEncodingException
  16. */
  17. public static String EncoderByMd5(String str) {
  18. if (str == null) {
  19. return null;
  20. }
  21. try {
  22. // 确定计算方法
  23. MessageDigest md5 = MessageDigest.getInstance("MD5");
  24. BASE64Encoder base64en = new BASE64Encoder();
  25. // 加密后的字符串
  26. return base64en.encode(md5.digest(str.getBytes("utf-8")));
  27. } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
  28. return null;
  29. }
  30. }
  31. }


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

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

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

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



===

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

---

  1. package com.sxz.common.utils;
  2. import java.io.UnsupportedEncodingException;
  3. import java.math.BigInteger;
  4. import java.security.MessageDigest;
  5. import java.security.NoSuchAlgorithmException;
  6. public class GetMD5Info {
  7. public static void main (String[] args) {
  8. System.out.println(EncoderByMd5("123"));
  9. }
  10. public static String EncoderByMd5(String str) {
  11. if (str == null) {
  12. return null;
  13. }
  14. String strMD5 = "";
  15. try {
  16. // 确定计算方法
  17. MessageDigest md5 = MessageDigest.getInstance("MD5");
  18. // 加密后的字符串
  19. byte[] bytes = md5.digest(str.getBytes("utf-8"));
  20. strMD5 = String.format("%032x", new BigInteger(1, bytes));
  21. } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
  22. return null;
  23. }
  24. return strMD5;
  25. }
  26. }

---

得到的结果是

202cb962ac59075b964b07152d234b70

---

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

===

  1. import lombok.extern.slf4j.Slf4j;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.nio.MappedByteBuffer;
  5. import java.nio.channels.FileChannel;
  6. import java.security.MessageDigest;
  7. @Slf4j
  8. public class SHA1 {
  9. protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E','F' };
  10. /**
  11. * @Description: 计算SHA1码
  12. * @Param file
  13. * @Return java.lang.String
  14. * @Author Menglong.Cao
  15. * @Date 2022/3/1 16:43
  16. */
  17. public static String generate(File file){
  18. try{
  19. MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
  20. FileInputStream in = new FileInputStream(file);
  21. FileChannel ch = in.getChannel();
  22. MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY,0,file.length());
  23. messageDigest.update(byteBuffer);
  24. return bufferToHex(messageDigest.digest());
  25. }catch (Exception e){
  26. log.warn("generate-hash-fail:errorMessage={},{}",e.getMessage(),e);
  27. }
  28. return null;
  29. }
  30. private static String bufferToHex(byte bytes[]){
  31. return bufferToHex(bytes,0,bytes.length);
  32. }
  33. private static String bufferToHex(byte bytes[],int m,int n){
  34. StringBuffer stringBuffer = new StringBuffer(2*n);
  35. int k = m + n;
  36. for(int l = m; l < k; l++){
  37. appendHexPair(bytes[l],stringBuffer);
  38. }
  39. return stringBuffer.toString();
  40. }
  41. private static void appendHexPair(byte bt, StringBuffer stringBuffer){
  42. char c0 = hexDigits[(bt & 0xf0) >> 4];
  43. char c1 = hexDigits[bt & 0xf];
  44. stringBuffer.append(c0);
  45. stringBuffer.append(c1);
  46. }
  47. //测试
  48. public static void main(String[] args) throws Exception{
  49. System.out.println("begin...");
  50. long begin = System.currentTimeMillis();
  51. File file2 = new File("D:\\计算hash.txt");
  52. String sha1 = SHA1.generate(file2);
  53. System.out.println("文件hash:"+sha1);// 82C189E0D231901FFC0597401F75CB54F44331A8
  54. System.out.println("耗时:"+(System.currentTimeMillis()-begin)+"ms");
  55. System.out.println("end...");
  56. }
  57. }

----

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

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

  1. package com.sxz.study.algorithm;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.math.BigInteger;
  6. import java.security.MessageDigest;
  7. import java.security.NoSuchAlgorithmException;
  8. public class TestMD5File {
  9. public static void main(String[] args) {
  10. String md5str = getMD5Three("C:\\eclipse\\下载的plugin\\ERMaster\\org.insightech.er_1.0.0.v20150619-0219.jar");
  11. System.out.println(md5str);
  12. }
  13. public static String getMD5Three(String path) {
  14. BigInteger bi = null;
  15. try {
  16. byte[] buffer = new byte[8192];
  17. int len = 0;
  18. MessageDigest md = MessageDigest.getInstance("MD5");
  19. File f = new File(path);
  20. FileInputStream fis = new FileInputStream(f);
  21. while ((len = fis.read(buffer)) != -1) {
  22. md.update(buffer, 0, len);
  23. }
  24. fis.close();
  25. byte[] b = md.digest();
  26. bi = new BigInteger(1, b);
  27. } catch (NoSuchAlgorithmException e) {
  28. e.printStackTrace();
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. // 下面代码有BUG,当MD5的Hash值,第一位是0是,第一位会被省略。
  33. // return bi.toString(16);
  34. // 使用下面代码解决bug (MD5的值,是一个32位长度的字符串)
  35. String md5Str = bi.toString(16);
  36. String md5StrFormat = md5Str.format("%32s", mdtStr); // 不足32位,前面补空格
  37. String result= md5StrFormat.replace(" ", "0"); // 把空格替换成0
  38. String result.toUpperCase();
  39. }
  40. }

代码运行结果

 PowerShell生成的MD5  (完全相同)

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

==

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/730869
推荐阅读
相关标签
  

闽ICP备14008679号