密钥验证的流程如下:
假如我们需要做一个服务,让用户通过密钥验证的方式来访问服务内容。客户端通过调用服务端程序生成密钥并返回客户端,并再次传入验证密钥到服务段进行密钥验证。客户端这边通过用户名密码和密钥申请时间等字段共同生成密钥,密钥相关代码如下:
复制代码
1
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13import org.apache.commons.codec.binary.Hex; import org.apache.commons.io.IOUtils; import java.io.*; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern;
复制代码
1
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287public class RSAUtils { private static final String SIGN_ALGORITHMS = "SHA256withRSA"; private static final String OLD_SIGN_ALGORITHMS = "SHA1withRSA"; private static final Map<String, PrivateKey> PRIVATEKEY_CACHE = new ConcurrentHashMap<>(); private static final Map<String, PublicKey> PUBLICKEY_CACHE = new ConcurrentHashMap<>(); private static InputStream getResourceAsStream(String resource) throws IOException { InputStream in = null; ClassLoader loader = RSAUtils.class.getClassLoader(); if (loader != null) { in = loader.getResourceAsStream(resource); } if (in == null) { in = ClassLoader.getSystemResourceAsStream(resource); } if (in == null) { throw new IOException("请将密钥文件" + resource + "放到工程classpath目录!"); } return in; } public static PrivateKey getPrivateKey(String key) { if (PRIVATEKEY_CACHE.containsKey(key)) { return PRIVATEKEY_CACHE.get(key); } PrivateKey privateKey = null; try { InputStream in = getResourceAsStream(key); if (in == null) { return null; } byte[] keyBytes = IOUtils.toByteArray(in); IOUtils.closeQuietly(in); privateKey = bytesToPrivateKey(keyBytes); PRIVATEKEY_CACHE.put(key, privateKey); } catch (Exception e) { e.printStackTrace(); } return privateKey; } public static PublicKey getPublicKey(String key) { if (PUBLICKEY_CACHE.containsKey(key)) { return PUBLICKEY_CACHE.get(key); } PublicKey publicKey = null; try { InputStream in = getResourceAsStream(key); if (in == null) { return null; } byte[] keyBytes = IOUtils.toByteArray(in); IOUtils.closeQuietly(in); publicKey = bytesToPublicKey(keyBytes); PUBLICKEY_CACHE.put(key, publicKey); } catch (Exception e) { e.printStackTrace(); } return publicKey; } /** * * 生成密钥对 * * * @return KeyPair * * @throws Exception */ public static KeyPair generateKeyPair() throws Exception { try { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); // 没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低 final int keySize = 2048; keyPairGen.initialize(keySize, new SecureRandom()); return keyPairGen.generateKeyPair(); } catch (Exception e) { throw new Exception(e.getMessage()); } } /*** * 使用私钥对数据签名 * @param content 待签名数据 * @param privateKey 私钥 * @return 签名数据 */ public static String sign(String content, PrivateKey privateKey) { try { Signature signature = Signature.getInstance(SIGN_ALGORITHMS); signature.initSign(privateKey); signature.update(content.getBytes("UTF-8")); byte[] signed = signature.sign(); return Base64.getEncoder().encodeToString(signed); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 使用公钥对签名数据进行验证 * * @param content 待签名数据 * @param sign 签名数据 * @param publicKey 公钥 * @return 验证结果 */ public static boolean verify(String content, String sign, PublicKey publicKey) { try { if (Pattern.matches("^[0-9a-f]+$", sign)) { Signature signature = Signature.getInstance(OLD_SIGN_ALGORITHMS); signature.initVerify(publicKey); signature.update(content.getBytes("UTF-8")); return signature.verify(Hex.decodeHex(sign.toCharArray())); } else { Signature signature = Signature.getInstance(SIGN_ALGORITHMS); signature.initVerify(publicKey); signature.update(content.getBytes("UTF-8")); return signature.verify(Base64.getDecoder().decode(sign)); } } catch (Exception e) { e.printStackTrace(); } return false; } /** * 将公钥/私钥转为base64格式密钥串 * * @param key * @return * @throws IOException */ public static String keyToString(Key key) { byte[] keyBytes = key.getEncoded(); return Base64.getEncoder().encodeToString(keyBytes); } /** * 将公钥/私钥转为base64格式密钥byte数组 * * @param key * @return * @throws IOException */ public static byte[] keyToBytes(Key key) { byte[] keyBytes = key.getEncoded(); return Base64.getEncoder().encode(keyBytes); } /** * 将pkcs8 base64 的byte数组转为私钥 * * @param bytes * @return * @throws InvalidKeySpecException * @throws NoSuchAlgorithmException */ public static PrivateKey bytesToPrivateKey(byte[] bytes) throws InvalidKeySpecException, NoSuchAlgorithmException { byte[] encodedKey = Base64.getDecoder().decode(bytes); KeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(keySpec); } /** * 将x509 base64 byte数组转为公钥 * * @param bytes * @return * @throws InvalidKeySpecException * @throws NoSuchAlgorithmException */ public static PublicKey bytesToPublicKey(byte[] bytes) throws InvalidKeySpecException, NoSuchAlgorithmException { byte[] encodedKey = Base64.getDecoder().decode(bytes); KeySpec keySpec = new X509EncodedKeySpec(encodedKey); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(keySpec); }
服务器端利用上述代码生成密钥代码如下:
复制代码
1
复制代码
1
2static KeyPair kp ; static PublicKey publicKey;//为了使验证时,使用与生成密钥时对应的公钥,在此设置为静态域。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49public String getmy(String str) throws Exception { Map map=new HashMap(); String name; String userid=(String)map.get("userid"); String jh100005=(String)map.get("jh100005"); String service=(String)map.get("service"); Map map2=new HashMap(); kp = RSAUtils.generateKeyPair(); long rtime = new Date().getTime(); String rtimes = Long.toString(rtime); String ser=(String)map.get("service"); String content = rtimes + userid+ser; String sign = RSAUtils.sign(content, kp.getPrivate());//生成密钥 publicKey=kp.getPublic();//publicKey为静态域, System.out.println("publickey="+publicKey); String publickeystring=keyToString(publicKey); //计算24小时之后时间,设定密钥的有效期。 Date date=new Date(); Calendar cal=new GregorianCalendar(); cal.setTime(date); cal.add(cal.DATE, 1); Date tomorrow=cal.getTime(); long tomortime=tomorrow.getTime(); return sign ;}
复制代码
1
2
验证密钥:
复制代码
整个生成验证的流程就完成了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29public String verify(String str) throws Exception { ExchViewSerService exchViewSerService = (ExchViewSerService) ServiceLocator.getService("exchViewSerService"); Map map=new HashMap(); String yzmy= (String) map.get("yzmy");//获取用户输入的密钥字段。 String hmopubkey;//公钥 String content;//生成密钥时使用的字符串。 HashMap hmo1=(HashMap)o; //o为从数据库中读取的密钥相关字段,为一个map对象。 hmopubkey=(String)hmo1.get("publickeystring");//取出公钥字符 content=(String)hmo1.get("content");//取出内容。 long date= Long.parseLong(hmo1.get("signeffectime").toString());//取出密钥有效终止日期 System.out.println(date); //判断是否过期 Date datenow=new Date(); long sub=date-datenow.getTime(); System.out.println(sub); if(sub<0){ map.put("mygq","密钥过期"); return "密钥过期"; } boolean sucessflag=RSAUtils.verify(content,yzmy,publicKey);//判断密钥是否正确。 map.put("flag", sucessflag); if(sucessflag){ System.out.println("sucess"); return "sucess";} else{ return "false"; } }
最后
以上就是传统人生最近收集整理的关于通过Rsa加密验证。的全部内容,更多相关通过Rsa加密验证内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复