1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.crypto;
16
17 import java.util.Set;
18
19 import org.htmlunit.corejs.javascript.Scriptable;
20 import org.htmlunit.corejs.javascript.ScriptableObject;
21 import org.htmlunit.corejs.javascript.VarScope;
22 import org.htmlunit.javascript.JavaScriptEngine;
23
24
25
26
27
28
29
30
31 final class HmacKeyAlgorithm {
32
33 static final Set<String> SUPPORTED_HASH_ALGORITHMS = Set.of("SHA-1", "SHA-256", "SHA-384", "SHA-512");
34
35 private final String hash_;
36 private final int length_;
37
38 HmacKeyAlgorithm(final String hash, final int length) {
39 if (!SUPPORTED_HASH_ALGORITHMS.contains(hash)) {
40 throw new UnsupportedOperationException("HMAC " + hash);
41 }
42 hash_ = hash;
43
44 if (length <= 0) {
45 throw new IllegalArgumentException("Data provided to an operation does not meet requirements");
46 }
47 length_ = length;
48 }
49
50
51
52
53
54
55
56 static HmacKeyAlgorithm from(final Scriptable keyGenParams) {
57 return from(keyGenParams, null);
58 }
59
60
61
62
63
64
65
66
67
68 static HmacKeyAlgorithm from(final Scriptable keyGenParams, final Integer fallbackLength) {
69 final Object hashProp = ScriptableObject.getProperty(keyGenParams, "hash");
70 final String hash = SubtleCrypto.resolveAlgorithmName(hashProp);
71
72 final int length;
73 final Object lengthProp = ScriptableObject.getProperty(keyGenParams, "length");
74 if (lengthProp == Scriptable.NOT_FOUND) {
75 if (fallbackLength != null) {
76 length = fallbackLength;
77 }
78 else {
79
80 length = switch (hash) {
81 case "SHA-1", "SHA-256" -> 512;
82 case "SHA-384", "SHA-512" -> 1024;
83 default -> throw new UnsupportedOperationException("HMAC " + hash);
84 };
85 }
86 }
87 else {
88 if (!(lengthProp instanceof Number numLength)) {
89 throw new IllegalArgumentException("An invalid or illegal string was specified");
90 }
91 length = numLength.intValue();
92 }
93
94 return new HmacKeyAlgorithm(hash, length);
95 }
96
97 String getHash() {
98 return hash_;
99 }
100
101 int getLength() {
102 return length_;
103 }
104
105
106
107
108 String getJavaName() {
109 return "Hmac" + hash_.replace("-", "");
110 }
111
112
113
114
115
116
117
118
119 Scriptable toScriptableObject(final VarScope scope) {
120 final Scriptable hashObj = JavaScriptEngine.newObject(scope);
121 ScriptableObject.putProperty(hashObj, "name", getHash());
122
123 final Scriptable algorithm = JavaScriptEngine.newObject(scope);
124 ScriptableObject.putProperty(algorithm, "name", "HMAC");
125 ScriptableObject.putProperty(algorithm, "hash", hashObj);
126 ScriptableObject.putProperty(algorithm, "length", getLength());
127 return algorithm;
128 }
129 }