1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package es.accv.arangi.base.certificate.validation;
22
23 import java.io.ByteArrayInputStream;
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileNotFoundException;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.security.PublicKey;
30
31 import javax.security.auth.x500.X500Principal;
32
33 import org.apache.log4j.Logger;
34 import org.bouncycastle.asn1.ASN1Encoding;
35 import org.bouncycastle.asn1.DEROctetString;
36 import org.bouncycastle.asn1.DERSequence;
37 import org.bouncycastle.asn1.DERTaggedObject;
38 import org.bouncycastle.asn1.x500.X500Name;
39 import org.bouncycastle.cert.X509CertificateHolder;
40 import org.bouncycastle.cert.ocsp.BasicOCSPResp;
41 import org.bouncycastle.cert.ocsp.OCSPException;
42 import org.bouncycastle.cert.ocsp.OCSPResp;
43 import org.bouncycastle.operator.OperatorCreationException;
44 import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
45
46 import es.accv.arangi.base.ArangiObject;
47 import es.accv.arangi.base.certificate.Certificate;
48 import es.accv.arangi.base.exception.certificate.NormalizeCertificateException;
49 import es.accv.arangi.base.exception.certificate.validation.MalformedOCSPResponseException;
50 import es.accv.arangi.base.util.validation.ValidationResult;
51
52
53
54
55
56
57
58
59
60 public class OCSPResponse extends ArangiObject {
61
62
63
64
65 static Logger logger = Logger.getLogger(OCSPResponse.class);
66
67
68
69
70 private OCSPResp ocspResponse;
71
72
73
74
75 private BasicOCSPResp basicOcspResponse;
76
77
78
79
80 private CertificateOCSPResponse[] responses;
81
82
83
84
85
86
87
88
89
90
91 public OCSPResponse (OCSPResp ocspResponse) throws MalformedOCSPResponseException {
92
93 try {
94 this.ocspResponse = ocspResponse;
95 this.basicOcspResponse = (BasicOCSPResp)ocspResponse.getResponseObject();
96 } catch (OCSPException e) {
97 logger.info ("[OCSPResponse]::No se encuentra una respuesta básica OCSP en la respuesta OCSP", e);
98 throw new MalformedOCSPResponseException ("No se encuentra una respuesta básica OCSP en la respuesta OCSP", e);
99 } catch (ClassCastException e) {
100 logger.info ("[OCSPResponse]::El objeto contenido en la respuesta OCSP no es una respuesta básica OCSP y no puede ser tratada por esta clase", e);
101 throw new MalformedOCSPResponseException ("El objeto contenido en la respuesta OCSP no es una respuesta básica OCSP y no puede ser tratada por esta clase", e);
102 }
103
104
105 this.responses = getResponses (basicOcspResponse);
106 }
107
108
109
110
111
112
113
114
115
116
117 public OCSPResponse (File fileOCSPResponse) throws MalformedOCSPResponseException, FileNotFoundException {
118
119 FileInputStream fis = null;
120 try {
121 fis = new FileInputStream (fileOCSPResponse);
122 initialize (fis);
123 } finally {
124 if (fis != null) {
125 try {
126 fis.close();
127 } catch (IOException e) {
128 logger.info ("[OCSPResponse(file)]::No se ha podido cerrar el stream de lectura al fichero: " + fileOCSPResponse.getAbsolutePath(), e);
129 }
130 }
131 }
132 }
133
134
135
136
137
138
139
140
141
142 public OCSPResponse (byte[] bytesOCSPResponse) throws MalformedOCSPResponseException {
143 initialize (new ByteArrayInputStream (bytesOCSPResponse));
144 }
145
146
147
148
149
150
151
152
153
154 public OCSPResponse (InputStream isOCSPResponse) throws MalformedOCSPResponseException {
155 initialize (isOCSPResponse);
156 }
157
158
159
160
161
162
163
164
165
166 public boolean isSignatureValid () {
167 logger.debug ("[OCSPResponse.isSignatureValid]::Entrada");
168
169
170 Certificate signCertificate = getSignatureCertificate();
171
172
173 PublicKey keyCertificadoOCSP = signCertificate.getPublicKey();
174 try {
175 if (!basicOcspResponse.isSignatureValid(new JcaContentVerifierProviderBuilder().build(keyCertificadoOCSP))) {
176 logger.debug ("[OCSPResponse.isSignatureValid]::Los datos de la respuesta OCSP han sido modificados desde su firma");
177 return false;
178 }
179 } catch (OCSPException e) {
180 logger.info ("[OCSPResponse.isSignatureValid]::No se puede validar la firma", e);
181 return false;
182 } catch (OperatorCreationException e) {
183 logger.info ("[OCSPResponse.isSignatureValid]::No se puede construir el validador de la firma", e);
184 return false;
185 }
186
187 return true;
188
189 }
190
191
192
193
194
195
196 public Certificate getSignatureCertificate () {
197 logger.debug ("[OCSPResponse.getSignatureCertificate]::Entrada");
198
199 return OCSPResponse.getSignatureCertificate(this.basicOcspResponse);
200 }
201
202
203
204
205
206
207
208 public CertificateOCSPResponse[] getSingleResponses () {
209 return responses;
210 }
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227 public int getStatus (ValidateCertificate certificate) {
228 logger.debug("[OCSPResponse.getStatus]::Entrada");
229
230 for (int i = 0; i < responses.length; i++) {
231 if (responses[i].match(certificate)) {
232 return responses[i].getStatus();
233 }
234 }
235
236 return ValidationResult.RESULT_CERTIFICATE_CANNOT_BE_VALIDATED;
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256 public int getStatus () {
257 logger.debug("[OCSPResponse.getStatus]::Entrada");
258
259 if (responses.length == 0) {
260 return ValidationResult.RESULT_CERTIFICATE_CANNOT_BE_VALIDATED;
261 } else {
262 return responses[0].getStatus();
263 }
264 }
265
266
267
268
269
270
271 public String getResponderIdName () {
272 logger.debug("[OCSPResponse.getResponderIdName]::Entrada");
273
274 DERTaggedObject derTagged = (DERTaggedObject)basicOcspResponse.getResponderId().toASN1Primitive().toASN1Primitive();
275 if (!(derTagged.getObject() instanceof DERSequence)) {
276 logger.debug("[OCSPResponse.getResponderIdName]::Es un KeyHash y no un X509Name");
277 return null;
278 }
279 String valorResponder = X500Name.getInstance((DERSequence)derTagged.getObject()).toString();
280 X500Name certX509Principal = new X500Name(valorResponder);
281 X500Principal cerX500Principal;
282 try {
283 cerX500Principal = new X500Principal(certX509Principal.getEncoded(ASN1Encoding.DER));
284 } catch (IOException e) {
285 logger.debug("[OCSPResponse.getResponderIdName]::No se puede obtener el ResponderIDName", e);
286 return null;
287 }
288 return cerX500Principal.getName();
289
290 }
291
292
293
294
295
296
297 public String getResponderIdKeyHash () {
298 logger.debug("[OCSPResponse.getResponderIdKeyHash]::Entrada");
299
300 DERTaggedObject derTagged = (DERTaggedObject)basicOcspResponse.getResponderId().toASN1Primitive().toASN1Primitive();
301 if (derTagged.getObject() instanceof DERSequence) {
302 logger.debug("[OCSPResponse.getResponderIdKeyHash]::Es un X509Name y no un KeyHash");
303 return null;
304 }
305 return ((DEROctetString)derTagged.getObject()).toString();
306
307 }
308
309
310
311
312
313
314
315 public byte[] toDER () {
316 try {
317 return ocspResponse.getEncoded();
318 } catch (IOException e) {
319
320 logger.info("[OCSPResponse.toDER]::Error de entrada/salida", e);
321 return null;
322 }
323 }
324
325
326
327
328
329
330
331 public BasicOCSPResp getBasicOCSPResponse () {
332 return basicOcspResponse;
333 }
334
335
336
337
338
339
340
341
342 public static CertificateOCSPResponse[] getResponses (BasicOCSPResp basicOcspResponse) {
343
344 logger.debug ("[OCSPResponse.getListResponses]::Entrada::" + basicOcspResponse);
345
346
347 CertificateOCSPResponse[] responses = new CertificateOCSPResponse [basicOcspResponse.getResponses().length];
348 for (int i = 0; i < basicOcspResponse.getResponses().length; i++) {
349 responses [i] = new CertificateOCSPResponse (getSignatureCertificate(basicOcspResponse),
350 basicOcspResponse.getResponses() [i]);
351 }
352
353 return responses;
354 }
355
356
357
358
359
360
361
362
363 public static Certificate getSignatureCertificate (BasicOCSPResp basicOcspResponse) {
364 logger.debug ("[OCSPResponse.getSignatureCertificate]::Entrada::" + basicOcspResponse);
365
366 X509CertificateHolder[] certificatePath = basicOcspResponse.getCerts();
367
368
369
370 if (certificatePath == null || certificatePath.length == 0) {
371 logger.info("[OCSPResponse.getSignatureCertificate]::La respuesta OCSP no está firmada");
372 return null;
373 }
374
375 try {
376 return new Certificate (certificatePath[0]);
377 } catch (NormalizeCertificateException e) {
378 logger.info("[OCSPResponse.getSignatureCertificate]::El certificado no puede ser normalizado para el proveedor criptográfico de Arangi", e);
379 return null;
380 }
381
382 }
383
384
385
386
387
388
389 private void initialize (InputStream is) throws MalformedOCSPResponseException {
390
391
392 try {
393 ocspResponse = new OCSPResp (is);
394 basicOcspResponse = (BasicOCSPResp)ocspResponse.getResponseObject();
395 } catch (IOException e) {
396 logger.info ("[OCSPResponse.initialize]::El objeto no es una respuesta OCSP bien formada", e);
397 throw new MalformedOCSPResponseException ("El objeto no es una respuesta OCSP bien formada", e);
398 } catch (OCSPException e) {
399 logger.info ("[OCSPResponse.initialize]::No se encuentra una respuesta básica OCSP en la respuesta OCSP", e);
400 throw new MalformedOCSPResponseException ("No se encuentra una respuesta básica OCSP en la respuesta OCSP", e);
401 } catch (ClassCastException e) {
402 logger.info ("[OCSPResponse.initialize]::El objeto contenido en la respuesta OCSP no es una respuesta básica OCSP y no puede ser tratada por esta clase", e);
403 throw new MalformedOCSPResponseException ("El objeto contenido en la respuesta OCSP no es una respuesta básica OCSP y no puede ser tratada por esta clase", e);
404 }
405
406
407
408 this.responses = getResponses (basicOcspResponse);
409 }
410
411 }