Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/ec/ECKeyFactory.java
38830 views
1
/*
2
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.security.ec;
27
28
import java.security.*;
29
import java.security.interfaces.*;
30
import java.security.spec.*;
31
32
/**
33
* KeyFactory for EC keys. Keys must be instances of PublicKey or PrivateKey
34
* and getAlgorithm() must return "EC". For such keys, it supports conversion
35
* between the following:
36
*
37
* For public keys:
38
* . PublicKey with an X.509 encoding
39
* . ECPublicKey
40
* . ECPublicKeySpec
41
* . X509EncodedKeySpec
42
*
43
* For private keys:
44
* . PrivateKey with a PKCS#8 encoding
45
* . ECPrivateKey
46
* . ECPrivateKeySpec
47
* . PKCS8EncodedKeySpec
48
*
49
* @since 1.6
50
* @author Andreas Sterbenz
51
*/
52
public final class ECKeyFactory extends KeyFactorySpi {
53
54
// Used by translateKey()
55
private static KeyFactory instance;
56
57
private static KeyFactory getInstance() {
58
if (instance == null) {
59
try {
60
instance = KeyFactory.getInstance("EC", "SunEC");
61
} catch (NoSuchProviderException e) {
62
throw new RuntimeException(e);
63
} catch (NoSuchAlgorithmException e) {
64
throw new RuntimeException(e);
65
}
66
}
67
68
return instance;
69
}
70
71
public ECKeyFactory() {
72
// empty
73
}
74
75
/**
76
* Static method to convert Key into a useable instance of
77
* ECPublicKey or ECPrivateKey. Check the key and convert it
78
* to a Sun key if necessary. If the key is not an EC key
79
* or cannot be used, throw an InvalidKeyException.
80
*
81
* The difference between this method and engineTranslateKey() is that
82
* we do not convert keys of other providers that are already an
83
* instance of ECPublicKey or ECPrivateKey.
84
*
85
* To be used by future Java ECDSA and ECDH implementations.
86
*/
87
public static ECKey toECKey(Key key) throws InvalidKeyException {
88
if (key instanceof ECKey) {
89
ECKey ecKey = (ECKey)key;
90
checkKey(ecKey);
91
return ecKey;
92
} else {
93
/*
94
* We don't call the engineTranslateKey method directly
95
* because KeyFactory.translateKey adds code to loop through
96
* all key factories.
97
*/
98
return (ECKey)getInstance().translateKey(key);
99
}
100
}
101
102
/**
103
* Check that the given EC key is valid.
104
*/
105
private static void checkKey(ECKey key) throws InvalidKeyException {
106
// check for subinterfaces, omit additional checks for our keys
107
if (key instanceof ECPublicKey) {
108
if (key instanceof ECPublicKeyImpl) {
109
return;
110
}
111
} else if (key instanceof ECPrivateKey) {
112
if (key instanceof ECPrivateKeyImpl) {
113
return;
114
}
115
} else {
116
throw new InvalidKeyException("Neither a public nor a private key");
117
}
118
// ECKey does not extend Key, so we need to do a cast
119
String keyAlg = ((Key)key).getAlgorithm();
120
if (keyAlg.equals("EC") == false) {
121
throw new InvalidKeyException("Not an EC key: " + keyAlg);
122
}
123
// XXX further sanity checks about whether this key uses supported
124
// fields, point formats, etc. would go here
125
}
126
127
/**
128
* Translate an EC key into a Sun EC key. If conversion is
129
* not possible, throw an InvalidKeyException.
130
* See also JCA doc.
131
*/
132
protected Key engineTranslateKey(Key key) throws InvalidKeyException {
133
if (key == null) {
134
throw new InvalidKeyException("Key must not be null");
135
}
136
String keyAlg = key.getAlgorithm();
137
if (keyAlg.equals("EC") == false) {
138
throw new InvalidKeyException("Not an EC key: " + keyAlg);
139
}
140
if (key instanceof PublicKey) {
141
return implTranslatePublicKey((PublicKey)key);
142
} else if (key instanceof PrivateKey) {
143
return implTranslatePrivateKey((PrivateKey)key);
144
} else {
145
throw new InvalidKeyException("Neither a public nor a private key");
146
}
147
}
148
149
// see JCA doc
150
protected PublicKey engineGeneratePublic(KeySpec keySpec)
151
throws InvalidKeySpecException {
152
try {
153
return implGeneratePublic(keySpec);
154
} catch (InvalidKeySpecException e) {
155
throw e;
156
} catch (GeneralSecurityException e) {
157
throw new InvalidKeySpecException(e);
158
}
159
}
160
161
// see JCA doc
162
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
163
throws InvalidKeySpecException {
164
try {
165
return implGeneratePrivate(keySpec);
166
} catch (InvalidKeySpecException e) {
167
throw e;
168
} catch (GeneralSecurityException e) {
169
throw new InvalidKeySpecException(e);
170
}
171
}
172
173
// internal implementation of translateKey() for public keys. See JCA doc
174
private PublicKey implTranslatePublicKey(PublicKey key)
175
throws InvalidKeyException {
176
if (key instanceof ECPublicKey) {
177
if (key instanceof ECPublicKeyImpl) {
178
return key;
179
}
180
ECPublicKey ecKey = (ECPublicKey)key;
181
return new ECPublicKeyImpl(
182
ecKey.getW(),
183
ecKey.getParams()
184
);
185
} else if ("X.509".equals(key.getFormat())) {
186
byte[] encoded = key.getEncoded();
187
return new ECPublicKeyImpl(encoded);
188
} else {
189
throw new InvalidKeyException("Public keys must be instance "
190
+ "of ECPublicKey or have X.509 encoding");
191
}
192
}
193
194
// internal implementation of translateKey() for private keys. See JCA doc
195
private PrivateKey implTranslatePrivateKey(PrivateKey key)
196
throws InvalidKeyException {
197
if (key instanceof ECPrivateKey) {
198
if (key instanceof ECPrivateKeyImpl) {
199
return key;
200
}
201
ECPrivateKey ecKey = (ECPrivateKey)key;
202
return new ECPrivateKeyImpl(
203
ecKey.getS(),
204
ecKey.getParams()
205
);
206
} else if ("PKCS#8".equals(key.getFormat())) {
207
return new ECPrivateKeyImpl(key.getEncoded());
208
} else {
209
throw new InvalidKeyException("Private keys must be instance "
210
+ "of ECPrivateKey or have PKCS#8 encoding");
211
}
212
}
213
214
// internal implementation of generatePublic. See JCA doc
215
private PublicKey implGeneratePublic(KeySpec keySpec)
216
throws GeneralSecurityException {
217
if (keySpec instanceof X509EncodedKeySpec) {
218
X509EncodedKeySpec x509Spec = (X509EncodedKeySpec)keySpec;
219
return new ECPublicKeyImpl(x509Spec.getEncoded());
220
} else if (keySpec instanceof ECPublicKeySpec) {
221
ECPublicKeySpec ecSpec = (ECPublicKeySpec)keySpec;
222
return new ECPublicKeyImpl(
223
ecSpec.getW(),
224
ecSpec.getParams()
225
);
226
} else {
227
throw new InvalidKeySpecException("Only ECPublicKeySpec "
228
+ "and X509EncodedKeySpec supported for EC public keys");
229
}
230
}
231
232
// internal implementation of generatePrivate. See JCA doc
233
private PrivateKey implGeneratePrivate(KeySpec keySpec)
234
throws GeneralSecurityException {
235
if (keySpec instanceof PKCS8EncodedKeySpec) {
236
PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec)keySpec;
237
return new ECPrivateKeyImpl(pkcsSpec.getEncoded());
238
} else if (keySpec instanceof ECPrivateKeySpec) {
239
ECPrivateKeySpec ecSpec = (ECPrivateKeySpec)keySpec;
240
return new ECPrivateKeyImpl(ecSpec.getS(), ecSpec.getParams());
241
} else {
242
throw new InvalidKeySpecException("Only ECPrivateKeySpec "
243
+ "and PKCS8EncodedKeySpec supported for EC private keys");
244
}
245
}
246
247
protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
248
throws InvalidKeySpecException {
249
try {
250
// convert key to one of our keys
251
// this also verifies that the key is a valid EC key and ensures
252
// that the encoding is X.509/PKCS#8 for public/private keys
253
key = engineTranslateKey(key);
254
} catch (InvalidKeyException e) {
255
throw new InvalidKeySpecException(e);
256
}
257
if (key instanceof ECPublicKey) {
258
ECPublicKey ecKey = (ECPublicKey)key;
259
if (ECPublicKeySpec.class.isAssignableFrom(keySpec)) {
260
return keySpec.cast(new ECPublicKeySpec(
261
ecKey.getW(),
262
ecKey.getParams()
263
));
264
} else if (X509EncodedKeySpec.class.isAssignableFrom(keySpec)) {
265
return keySpec.cast(new X509EncodedKeySpec(key.getEncoded()));
266
} else {
267
throw new InvalidKeySpecException
268
("KeySpec must be ECPublicKeySpec or "
269
+ "X509EncodedKeySpec for EC public keys");
270
}
271
} else if (key instanceof ECPrivateKey) {
272
if (PKCS8EncodedKeySpec.class.isAssignableFrom(keySpec)) {
273
return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded()));
274
} else if (ECPrivateKeySpec.class.isAssignableFrom(keySpec)) {
275
ECPrivateKey ecKey = (ECPrivateKey)key;
276
return keySpec.cast(new ECPrivateKeySpec(
277
ecKey.getS(),
278
ecKey.getParams()
279
));
280
} else {
281
throw new InvalidKeySpecException
282
("KeySpec must be ECPrivateKeySpec or "
283
+ "PKCS8EncodedKeySpec for EC private keys");
284
}
285
} else {
286
// should not occur, caught in engineTranslateKey()
287
throw new InvalidKeySpecException("Neither public nor private key");
288
}
289
}
290
}
291
292