1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.quic;
17
18 import io.netty.util.concurrent.FastThreadLocal;
19
20 import javax.crypto.Mac;
21 import javax.crypto.spec.SecretKeySpec;
22 import java.nio.ByteBuffer;
23 import java.security.InvalidKeyException;
24 import java.security.NoSuchAlgorithmException;
25 import java.security.SecureRandom;
26 import java.util.Arrays;
27
28 final class Hmac {
29
30 private static final FastThreadLocal<Mac> MACS = new FastThreadLocal<Mac>() {
31 @Override
32 protected Mac initialValue() {
33 return newMac();
34 }
35 };
36
37 private static final String ALGORITM = "HmacSHA256";
38 private static final byte[] randomKey = new byte[16];
39
40 static {
41 new SecureRandom().nextBytes(randomKey);
42 }
43
44 private static Mac newMac() {
45 try {
46 SecretKeySpec keySpec = new SecretKeySpec(randomKey, ALGORITM);
47 Mac mac = Mac.getInstance(ALGORITM);
48 mac.init(keySpec);
49 return mac;
50 } catch (NoSuchAlgorithmException | InvalidKeyException exception) {
51 throw new IllegalStateException(exception);
52 }
53 }
54
55 static ByteBuffer sign(ByteBuffer input, int outLength) {
56 Mac mac = MACS.get();
57 mac.reset();
58 mac.update(input);
59 byte[] signBytes = mac.doFinal();
60 if (signBytes.length != outLength) {
61 signBytes = Arrays.copyOf(signBytes, outLength);
62 }
63 return ByteBuffer.wrap(signBytes);
64 }
65
66 private Hmac() { }
67 }