1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.forgerock.json.jose.jws;
18
19 import java.math.BigInteger;
20 import java.security.interfaces.ECKey;
21 import java.security.spec.ECFieldFp;
22 import java.security.spec.ECParameterSpec;
23 import java.security.spec.ECPoint;
24 import java.security.spec.EllipticCurve;
25 import java.util.Objects;
26 import javax.xml.bind.DatatypeConverter;
27
28
29
30
31 public enum SupportedEllipticCurve {
32
33 P256("P-256", StandardCurve.P_256, 64, JwsAlgorithm.ES256),
34
35 P384("P-384", StandardCurve.P_384, 96, JwsAlgorithm.ES384),
36
37
38 P521("P-521", StandardCurve.P_521, 132, JwsAlgorithm.ES512);
39
40
41 private final ECParameterSpec parameters;
42 private final String standardName;
43 private final int signatureSize;
44 private final JwsAlgorithm jwsAlgorithm;
45
46 SupportedEllipticCurve(String standardName, ECParameterSpec curve, int signatureSize, JwsAlgorithm jwsAlgorithm) {
47 this.parameters = curve;
48 this.standardName = standardName;
49 this.signatureSize = signatureSize;
50 this.jwsAlgorithm = jwsAlgorithm;
51 }
52
53
54
55
56
57
58 public ECParameterSpec getParameters() {
59 return parameters;
60 }
61
62
63
64
65
66
67 public String getStandardName() {
68 return standardName;
69 }
70
71
72
73
74
75
76 public int getSignatureSize() {
77 return signatureSize;
78 }
79
80
81
82
83
84
85 public JwsAlgorithm getJwsAlgorithm() {
86 return jwsAlgorithm;
87 }
88
89
90
91
92
93
94
95
96 public static SupportedEllipticCurve forName(final String curveName) {
97 for (SupportedEllipticCurve candidate : values()) {
98 if (candidate.getStandardName().equals(curveName)) {
99 return candidate;
100 }
101 }
102 throw new IllegalArgumentException("Unsupported curve: " + curveName);
103 }
104
105
106
107
108
109
110
111
112
113
114 public static SupportedEllipticCurve forKey(final ECKey key) {
115 final ECParameterSpec params = key.getParams();
116 for (SupportedEllipticCurve supported : values()) {
117 final ECParameterSpec candidateParams = supported.getParameters();
118 if (candidateParams.getCofactor() == params.getCofactor()
119 && Objects.equals(candidateParams.getCurve(), params.getCurve())
120 && Objects.equals(candidateParams.getGenerator(), params.getGenerator())
121 && Objects.equals(candidateParams.getOrder(), params.getOrder())) {
122 return supported;
123 }
124 }
125 throw new IllegalArgumentException("Unsupported ECKey parameters");
126 }
127
128
129
130
131
132
133
134
135
136 public static SupportedEllipticCurve forSignature(byte[] signature) {
137 for (SupportedEllipticCurve candidate : values()) {
138 if (signature.length == candidate.getSignatureSize()) {
139 return candidate;
140 }
141 }
142 throw new IllegalArgumentException("Unsupported signature size: " + signature.length);
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 private static class StandardCurve {
202 private static final int H = 1;
203
204
205
206
207 private static final ECParameterSpec P_256 = new ECParameterSpec(
208 new EllipticCurve(
209 p("115792089210356248762697446949407573530086143415290314195533631308867097853951"),
210 a("115792089210356248762697446949407573530086143415290314195533631308867097853948"),
211 b("41058363725152142129326129780047268409114441015993725554835256314039467401291"),
212 seed("c49d3608 86e70493 6a6678e1 139d26b7 819f7e90")),
213 new ECPoint(x("48439561293906451759052585252797914202762949526041747995844080717082404635286"),
214 y("36134250956749795798585127919587881956611106672985015071877198253568414405109")),
215 n("115792089210356248762697446949407573529996955224135760342422259061068512044369"), H);
216
217
218
219
220 private static final ECParameterSpec P_384 = new ECParameterSpec(
221 new EllipticCurve(
222 p("3940200619639447921227904010014361380507973927046544666794829340424572177149687032904726"
223 + "6088258938001861606973112319"),
224 a("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088"
225 + "258938001861606973112316"),
226 b("27580193559959705877849011840389048093056905856361568521428707301988689241309860865136260764"
227 + "883745107765439761230575"),
228 seed("a335926a a319a27a 1d00896a 6773a482 7acdac73")),
229 new ECPoint(
230 x("26247035095799689268623156744566981891852923491109213387815615900925518854738050089022388053"
231 + "975719786650872476732087"),
232 y("83257109614890299855467512895201081792878530488613155947092059024805031998844192244386437603"
233 + "92947333078086511627871")),
234 n("3940200619639447921227904010014361380507973927046544666794690527962765939911326356939895630815229491"
235 + "3554433653942643"), H);
236
237
238
239
240 private static final ECParameterSpec P_521 = new ECParameterSpec(
241 new EllipticCurve(
242 p("68647976601306097149819007990813932172694353001433054093944634591855431833976560521225596406"
243 + "61454554977296311391480858037121987999716643812574028291115057151"),
244 a("68647976601306097149819007990813932172694353001433054093944634591855431833976560521225596406"
245 + "61454554977296311391480858037121987999716643812574028291115057148"),
246 b("10938490380737342745111123907668055699362075989516837489945863944959531161507350160137087375"
247 + "73759623248592132296706313309438452531591012912142327488478985984"),
248 seed("d09e8800 291cb853 96cc6717 393284aa a0da64ba")),
249 new ECPoint(
250 x("26617408020502170632287687167233609607298591687569731477066713684188029449964278084915450806"
251 + "27771902352094241225065558662157113545570916814161637315895999846"),
252 y("37571800257700204635455072244911836035944551347697624866945677796155444774405563166912344050"
253 + "12945539562144444537289428522585666729196580810124344277578376784")),
254 n("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197"
255 + "532963996371363321113864768612440380340372808892707005449"), H);
256
257
258 private static ECFieldFp p(final String value) {
259 return new ECFieldFp(new BigInteger(value));
260 }
261
262 private static BigInteger a(final String value) {
263 return new BigInteger(value);
264 }
265
266 private static BigInteger b(final String value) {
267 return new BigInteger(value);
268 }
269
270 private static BigInteger x(final String value) {
271 return new BigInteger(value);
272 }
273
274 private static BigInteger y(final String value) {
275 return new BigInteger(value);
276 }
277
278 private static BigInteger n(final String value) {
279 return new BigInteger(value);
280 }
281
282 private static byte[] seed(final String hex) {
283 return DatatypeConverter.parseHexBinary(hex.replaceAll("\\s+", ""));
284 }
285 }
286 }