1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.handler.codec.http.websocketx;
17
18 import io.netty5.util.CharsetUtil;
19 import io.netty5.util.concurrent.FastThreadLocal;
20
21 import java.security.MessageDigest;
22 import java.security.NoSuchAlgorithmException;
23 import java.util.Base64;
24 import java.util.concurrent.ThreadLocalRandom;
25
26
27
28
29 final class WebSocketUtil {
30
31 private static final String V13_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
32
33 private static final FastThreadLocal<MessageDigest> SHA1 = new FastThreadLocal<>() {
34 @Override
35 protected MessageDigest initialValue() throws Exception {
36 try {
37
38
39
40 return MessageDigest.getInstance("SHA-1");
41 } catch (NoSuchAlgorithmException e) {
42
43 throw new InternalError("SHA-1 not supported on this platform - Outdated ?");
44 }
45 }
46 };
47
48
49
50
51
52
53
54 static byte[] sha1(byte[] data) {
55 MessageDigest sha1Digest = SHA1.get();
56 sha1Digest.reset();
57 return sha1Digest.digest(data);
58 }
59
60
61
62
63
64
65
66 static String base64(byte[] data) {
67 return Base64.getEncoder().encodeToString(data);
68 }
69
70
71
72
73
74
75
76 static byte[] randomBytes(int size) {
77 var bytes = new byte[size];
78 ThreadLocalRandom.current().nextBytes(bytes);
79 return bytes;
80 }
81
82 static String calculateV13Accept(String nonce) {
83 String concat = nonce + V13_ACCEPT_GUID;
84 byte[] sha1 = WebSocketUtil.sha1(concat.getBytes(CharsetUtil.US_ASCII));
85 return WebSocketUtil.base64(sha1);
86 }
87
88 private WebSocketUtil() {
89 }
90 }