Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/security/provider/certpath/ResponderId.java
41161 views
1
/*
2
* Copyright (c) 2015, 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.provider.certpath;
27
28
import java.util.Arrays;
29
import java.io.IOException;
30
import java.security.PublicKey;
31
import javax.security.auth.x500.X500Principal;
32
import sun.security.x509.KeyIdentifier;
33
import sun.security.util.DerValue;
34
35
/**
36
* Class for ResponderId entities as described in RFC6960. ResponderId objects
37
* are used to uniquely identify OCSP responders.
38
* <p>
39
* The RFC 6960 defines a ResponderID structure as:
40
* <pre>
41
* ResponderID ::= CHOICE {
42
* byName [1] Name,
43
* byKey [2] KeyHash }
44
*
45
* KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
46
* (excluding the tag and length fields)
47
*
48
* Name is defined in RFC 5280.
49
* </pre>
50
*
51
* @see ResponderId.Type
52
* @since 9
53
*/
54
public final class ResponderId {
55
56
/**
57
* A {@code ResponderId} enumeration describing the accepted forms for a
58
* {@code ResponderId}.
59
*
60
* @see ResponderId
61
* @since 9
62
*/
63
public static enum Type {
64
/**
65
* A BY_NAME {@code ResponderId} will be built from a subject name,
66
* either as an {@code X500Principal} or a DER-encoded byte array.
67
*/
68
BY_NAME(1, "byName"),
69
70
/**
71
* A BY_KEY {@code ResponderId} will be built from a public key
72
* identifier, either derived from a {@code PublicKey} or directly
73
* from a DER-encoded byte array containing the key identifier.
74
*/
75
BY_KEY(2, "byKey");
76
77
private final int tagNumber;
78
private final String ridTypeName;
79
80
private Type(int value, String name) {
81
this.tagNumber = value;
82
this.ridTypeName = name;
83
}
84
85
public int value() {
86
return tagNumber;
87
}
88
89
@Override
90
public String toString() {
91
return ridTypeName;
92
}
93
}
94
95
private Type type;
96
private X500Principal responderName;
97
private KeyIdentifier responderKeyId;
98
private byte[] encodedRid;
99
100
/**
101
* Constructs a {@code ResponderId} object using an {@code X500Principal}.
102
* When encoded in DER this object will use the BY_NAME option.
103
*
104
* @param subjectName the subject name of the certificate used
105
* to sign OCSP responses.
106
*
107
* @throws IOException if the internal DER-encoding of the
108
* {@code X500Principal} fails.
109
*/
110
public ResponderId(X500Principal subjectName) throws IOException {
111
responderName = subjectName;
112
responderKeyId = null;
113
encodedRid = principalToBytes();
114
type = Type.BY_NAME;
115
}
116
117
/**
118
* Constructs a {@code ResponderId} object using a {@code PublicKey}.
119
* When encoded in DER this object will use the byKey option, a
120
* SHA-1 hash of the responder's public key.
121
*
122
* @param pubKey the OCSP responder's public key
123
*
124
* @throws IOException if the internal DER-encoding of the
125
* {@code KeyIdentifier} fails.
126
*/
127
public ResponderId(PublicKey pubKey) throws IOException {
128
responderKeyId = new KeyIdentifier(pubKey);
129
responderName = null;
130
encodedRid = keyIdToBytes();
131
type = Type.BY_KEY;
132
}
133
134
/**
135
* Constructs a {@code ResponderId} object from its DER-encoding.
136
*
137
* @param encodedData the DER-encoded bytes
138
*
139
* @throws IOException if the encodedData is not properly DER encoded
140
*/
141
public ResponderId(byte[] encodedData) throws IOException {
142
DerValue outer = new DerValue(encodedData);
143
144
if (outer.isContextSpecific((byte)Type.BY_NAME.value())
145
&& outer.isConstructed()) {
146
// Use the X500Principal constructor as a way to sanity
147
// check the incoming data.
148
responderName = new X500Principal(outer.getDataBytes());
149
encodedRid = principalToBytes();
150
type = Type.BY_NAME;
151
} else if (outer.isContextSpecific((byte)Type.BY_KEY.value())
152
&& outer.isConstructed()) {
153
// Use the KeyIdentifier constructor as a way to sanity
154
// check the incoming data.
155
responderKeyId =
156
new KeyIdentifier(new DerValue(outer.getDataBytes()));
157
encodedRid = keyIdToBytes();
158
type = Type.BY_KEY;
159
} else {
160
throw new IOException("Invalid ResponderId content");
161
}
162
}
163
164
/**
165
* Encode a {@code ResponderId} in DER form
166
*
167
* @return a byte array containing the DER-encoded representation for this
168
* {@code ResponderId}
169
*/
170
public byte[] getEncoded() {
171
return encodedRid.clone();
172
}
173
174
/**
175
* Return the type of {@ResponderId}
176
*
177
* @return a number corresponding to the context-specific tag number
178
* used in the DER-encoding for a {@code ResponderId}
179
*/
180
public ResponderId.Type getType() {
181
return type;
182
}
183
184
/**
185
* Get the length of the encoded {@code ResponderId} (including the tag and
186
* length of the explicit tagging from the outer ASN.1 CHOICE).
187
*
188
* @return the length of the encoded {@code ResponderId}
189
*/
190
public int length() {
191
return encodedRid.length;
192
}
193
194
/**
195
* Obtain the underlying {@code X500Principal} from a {@code ResponderId}
196
*
197
* @return the {@code X500Principal} for this {@code ResponderId} if it
198
* is a BY_NAME variant. If the {@code ResponderId} is a BY_KEY
199
* variant, this routine will return {@code null}.
200
*/
201
public X500Principal getResponderName() {
202
return responderName;
203
}
204
205
/**
206
* Obtain the underlying key identifier from a {@code ResponderId}
207
*
208
* @return the {@code KeyIdentifier} for this {@code ResponderId} if it
209
* is a BY_KEY variant. If the {@code ResponderId} is a BY_NAME
210
* variant, this routine will return {@code null}.
211
*/
212
public KeyIdentifier getKeyIdentifier() {
213
return responderKeyId;
214
}
215
216
/**
217
* Compares the specified object with this {@code ResponderId} for equality.
218
* A ResponderId will only be considered equivalent if both the type and
219
* data value are equal. Two ResponderIds initialized by name and
220
* key ID, respectively, will not be equal even if the
221
* ResponderId objects are created from the same source certificate.
222
*
223
* @param obj the object to be compared against
224
*
225
* @return true if the specified object is equal to this {@code Responderid}
226
*/
227
@Override
228
public boolean equals(Object obj) {
229
if (obj == null) {
230
return false;
231
}
232
233
if (this == obj) {
234
return true;
235
}
236
237
if (obj instanceof ResponderId) {
238
ResponderId respObj = (ResponderId)obj;
239
return Arrays.equals(encodedRid, respObj.getEncoded());
240
}
241
242
return false;
243
}
244
245
/**
246
* Returns the hash code value for this {@code ResponderId}
247
*
248
* @return the hash code value for this {@code ResponderId}
249
*/
250
@Override
251
public int hashCode() {
252
return Arrays.hashCode(encodedRid);
253
}
254
255
/**
256
* Create a String representation of this {@code ResponderId}
257
*
258
* @return a String representation of this {@code ResponderId}
259
*/
260
@Override
261
public String toString() {
262
StringBuilder sb = new StringBuilder();
263
switch (type) {
264
case BY_NAME:
265
sb.append(type).append(": ").append(responderName);
266
break;
267
case BY_KEY:
268
sb.append(type).append(": ");
269
for (byte keyIdByte : responderKeyId.getIdentifier()) {
270
sb.append(String.format("%02X", keyIdByte));
271
}
272
break;
273
default:
274
sb.append("Unknown ResponderId Type: ").append(type);
275
}
276
return sb.toString();
277
}
278
279
/**
280
* Convert the responderName data member into its DER-encoded form
281
*
282
* @return the DER encoding for a responder ID byName option, including
283
* explicit context-specific tagging.
284
*
285
* @throws IOException if any encoding error occurs
286
*/
287
private byte[] principalToBytes() throws IOException {
288
DerValue dv = new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
289
true, (byte)Type.BY_NAME.value()),
290
responderName.getEncoded());
291
return dv.toByteArray();
292
}
293
294
/**
295
* Convert the responderKeyId data member into its DER-encoded form
296
*
297
* @return the DER encoding for a responder ID byKey option, including
298
* explicit context-specific tagging.
299
*
300
* @throws IOException if any encoding error occurs
301
*/
302
private byte[] keyIdToBytes() throws IOException {
303
// Place the KeyIdentifier bytes into an OCTET STRING
304
DerValue inner = new DerValue(DerValue.tag_OctetString,
305
responderKeyId.getIdentifier());
306
307
// Mark the OCTET STRING-wrapped KeyIdentifier bytes
308
// as EXPLICIT CONTEXT 2
309
DerValue outer = new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
310
true, (byte)Type.BY_KEY.value()), inner.toByteArray());
311
312
return outer.toByteArray();
313
}
314
315
}
316
317