Skip to content

Commit 5ba9d90

Browse files
committed
master消息认证结束
1 parent 49ccefd commit 5ba9d90

5 files changed

Lines changed: 341 additions & 40 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.gitignore
2-
.idea/
32
.gradle/
3+
.idea/
44
gradle/
55
out/

.idea/workspace.xml

Lines changed: 51 additions & 39 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
# 哈希算法
2+
### 概念
3+
4+
称谓: 单向散列函数, 哈希函数, 杂凑函数, 消息摘要函数
5+
6+
接收的输入: 原像
7+
8+
输出: 散列值, 哈希值, 指纹, 摘要
9+
10+
### 单向散列函数特性
11+
12+
1. 将任意长度的数据转换成固定长度的数据
13+
2. 很强的抗碰撞性
14+
3. 不可逆
15+
4. MD4/MD5
16+
- 不安全
17+
- 散列值长度: 128bit == 16byte
18+
5. sha1
19+
- 不安全
20+
- 散列值长度: 160bit == 20byte
21+
6. sha2 - 安全
22+
- sha224
23+
- 散列值长度: 224bit == 28byte
24+
- sha256
25+
- 散列值长度: 256== 32byte
26+
- sha384
27+
- 散列值长度: 384bit == 48byte
28+
- sha512
29+
- 散列值长度: 512bit == 64byte
30+
7. 示例代码如下
31+
```$xslt
32+
public class HashDemo {
33+
public static void main(String[] args) throws Exception {
34+
String input = "frank";
35+
String md5 = getDigest(input, "MD5");
36+
System.out.println("md5:"+md5);
37+
String sha1 = getDigest(input, "SHA-1");
38+
System.out.println("sha1:"+sha1);
39+
String sha256 = getDigest(input, "SHA-256");
40+
System.out.println("sha256:"+sha256);
41+
String sha512 = getDigest(input, "SHA-512");
42+
System.out.println("sha512:"+sha512);
43+
44+
String fileSha1 = getDigestFile("jdk-8u191-windows-x64.exe", "SHA-1");
45+
System.out.println("fileSha1:"+fileSha1);
46+
47+
}
48+
49+
/**
50+
* 获取消息摘要
51+
*
52+
* @param input : 原文
53+
* @param algorithm : 算法
54+
* @return : 消息摘要
55+
* @throws Exception
56+
*/
57+
public static String getDigest(String input, String algorithm) throws Exception {
58+
// 获取MessageDigest对象
59+
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
60+
// 生成消息摘要
61+
byte[] digest = messageDigest.digest(input.getBytes());
62+
return toHex(digest);
63+
64+
}
65+
66+
/**
67+
*
68+
* @param filePath 文件路径
69+
* @param algorithm 算法
70+
* @return 返回对应的哈希值
71+
* @throws Exception
72+
*/
73+
public static String getDigestFile(String filePath, String algorithm) throws Exception {
74+
FileInputStream fis = new FileInputStream(filePath);
75+
int len;
76+
byte[] buffer = new byte[1024];
77+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
78+
while ((len = fis.read(buffer)) != -1) {
79+
baos.write(buffer, 0, len);
80+
}
81+
// 获取MessageDigest对象
82+
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
83+
// 生成消息摘要
84+
byte[] digest = messageDigest.digest(baos.toByteArray());
85+
return toHex(digest);
86+
87+
}
88+
89+
// 将字节数组转为16进制字符串
90+
public static String toHex(byte[] digest) {
91+
StringBuilder sb = new StringBuilder();
92+
for (byte b : digest) {
93+
int i = b & 0xff;
94+
String s = Integer.toHexString(i);
95+
if (s.length() == 1) {
96+
s = "0" + s;
97+
}
98+
sb.append(s);
99+
}
100+
return sb.toString();
101+
}
102+
}
103+
```
104+
105+
106+
## 消息认证码
107+
### 消息认证
108+
109+
> **消息认证码(message authentication code)是一种确认完整性并进行认证的技术,取三个单词的首字母,简称为MAC。**
110+
111+
![Logo](imgs/1.png)
112+
113+
- 思考改进方案?
114+
115+
从哈希函数入手
116+
117+
需要将要发送的数据进行哈希运算, 将哈希值和原始数据一并发送
118+
119+
需要在进行哈希运算的时候引入加密的步骤
120+
121+
- 在alice对数据进行哈希运算的时候引入一个秘钥, 让其参与哈希运算, 生成散列值
122+
- bob对数据校验
123+
- bob收到原始和散列值之后,
124+
- 处理原始数据: 通过秘钥和哈希算法对原始数据生成散列值
125+
- 散列值比较: 生成的散列值 和 接收到的散列值进行比对
126+
127+
### 消息认证码的使用步骤
128+
129+
![Logo](imgs/2.png)
130+
131+
> 1. 前提条件:
132+
> - 在消息认证码生成的一方和校验的一方, 必须有一个秘钥
133+
> - 双方约定好使用同样的哈希函数对数据进行运算
134+
> 2. 流程:
135+
> - 发送者:
136+
> - 发送原始法消息
137+
> - 将原始消息生成消息认证码
138+
> - ((原始消息) + 秘钥) * 函数函数 = 散列值(消息认证码)
139+
> - 将消息认证码发送给对方
140+
> - 接收者:
141+
> - 接收原始数据
142+
> - 接收消息认证码
143+
> - 校验:
144+
> - ( 接收的消息 + 秘钥 ) * 哈希函数 = 新的散列值
145+
> - 通过新的散列值和接收的散列值进行比较
146+
147+
### 消息认证码的问题
148+
149+
1. 弊端
150+
- 有秘钥分发困难的问题
151+
2. 无法解决的问题
152+
- 不能进行第三方证明
153+
- 不能防止否认
154+
3. 消息认证码常见的算法如下:
155+
![Logo](imgs/5.png)
156+
4. 消息认证代码如下:
157+
```$xslt
158+
public class MacDemo {
159+
public static void main(String[] args) throws Exception {
160+
String input = "frank";
161+
String keyString = "123DLLFLH";
162+
String algorithm = "HmacSHA256";
163+
164+
String hmac = generateHmac(input, keyString, algorithm);
165+
System.out.println(hmac);
166+
boolean b = verifyHamc("frank", keyString, algorithm, hmac);
167+
System.out.println(b);
168+
}
169+
170+
/**
171+
*
172+
* @param input 原文
173+
* @param keyString 秘钥
174+
* @param algorithm 算法
175+
* @return 返回的消息认证码
176+
* @throws Exception
177+
*/
178+
public static String generateHmac(String input,String keyString,String algorithm) throws Exception {
179+
Mac mac = Mac.getInstance(algorithm);
180+
Key key = new SecretKeySpec(keyString.getBytes(), "");
181+
mac.init(key);
182+
byte[] result = mac.doFinal(input.getBytes());
183+
String hmac = toHex(result);
184+
return hmac;
185+
}
186+
187+
/**
188+
* 消息认证
189+
* @param input 原文
190+
* @param keyString 秘钥序列
191+
* @param algorithm 算法
192+
* @param hmac 传入的消息认证码
193+
* @return
194+
* @throws Exception
195+
*/
196+
public static boolean verifyHamc(String input,String keyString,String algorithm,String hmac) throws Exception {
197+
String newHmac = generateHmac(input, keyString, algorithm);
198+
if (newHmac != null && newHmac.equals(hmac)) {
199+
return true;
200+
}
201+
return false;
202+
}
203+
204+
// 将字节数组转为16进制字符串
205+
public static String toHex(byte[] digest) {
206+
StringBuilder sb = new StringBuilder();
207+
for (byte b : digest) {
208+
int i = b & 0xff;
209+
String s = Integer.toHexString(i);
210+
if (s.length() == 1) {
211+
s = "0" + s;
212+
}
213+
sb.append(s);
214+
}
215+
return sb.toString();
216+
}
217+
}
218+
```

0 commit comments

Comments
 (0)