keycloak
クラス | 静的公開メンバ関数 | 静的関数 | 静的非公開メンバ関数 | 静的非公開変数類 | 全メンバ一覧
org.keycloak.common.util.OCSPUtils クラス
org.keycloak.common.util.OCSPUtils 連携図
Collaboration graph

クラス

interface  OCSPRevocationStatus
 
enum  RevocationStatus
 

静的公開メンバ関数

static OCSPRevocationStatus check (X509Certificate cert, X509Certificate issuerCertificate, URI responderURI, X509Certificate responderCert, Date date) throws CertPathValidatorException
 
static OCSPRevocationStatus check (X509Certificate cert, X509Certificate issuerCertificate, Date date, X509Certificate responderCert) throws CertPathValidatorException
 
static OCSPRevocationStatus check (X509Certificate cert, X509Certificate issuerCertificate) throws CertPathValidatorException
 

静的関数

 [static initializer]
 

静的非公開メンバ関数

static OCSPResp getResponse (OCSPReq ocspReq, URI responderUri) throws IOException
 
static OCSPRevocationStatus check (X509Certificate cert, X509Certificate issuerCertificate, List< URI > responderURIs, X509Certificate responderCert, Date date) throws CertPathValidatorException
 
static OCSPRevocationStatus processBasicOCSPResponse (X509Certificate issuerCertificate, X509Certificate responderCertificate, Date date, JcaCertificateID certificateID, BigInteger nounce, BasicOCSPResp basicOcspResponse) throws OCSPException, NoSuchProviderException, NoSuchAlgorithmException, CertificateNotYetValidException, CertificateExpiredException, CertPathValidatorException
 
static boolean compareCertIDs (JcaCertificateID idLeft, CertificateID idRight)
 
static void verifyResponse (BasicOCSPResp basicOcspResponse, X509Certificate issuerCertificate, X509Certificate responderCertificate, byte[] requestNonce, Date date) throws NoSuchProviderException, NoSuchAlgorithmException, CertificateNotYetValidException, CertificateExpiredException, CertPathValidatorException
 
static boolean verifySignature (BasicOCSPResp basicOcspResponse, X509Certificate cert)
 
static OCSPRevocationStatus unknownStatus ()
 
static OCSPRevocationStatus singleResponseToRevocationStatus (final SingleResp singleResponse) throws CertPathValidatorException
 
static List< String > getResponderURIs (X509Certificate cert) throws CertificateEncodingException
 

静的非公開変数類

static final Logger logger = Logger.getLogger(""+OCSPUtils.class)
 
static int OCSP_CONNECT_TIMEOUT = 10000
 
static final int TIME_SKEW = 900000
 

詳解

著者
Peter Nalyvayko
バージョン
Revision
1
から
10/29/2016

クラス詳解

◆ org::keycloak::common::util::OCSPUtils::RevocationStatus

enum org::keycloak::common::util::OCSPUtils::RevocationStatus
org.keycloak.common.util.OCSPUtils.RevocationStatus 連携図
Collaboration graph
列挙値
GOOD
REVOKED
UNKNOWN

関数詳解

◆ [static initializer]()

org.keycloak.common.util.OCSPUtils.[static initializer] ( )
inlinestaticpackage

◆ check() [1/4]

static OCSPRevocationStatus org.keycloak.common.util.OCSPUtils.check ( X509Certificate  cert,
X509Certificate  issuerCertificate,
URI  responderURI,
X509Certificate  responderCert,
Date  date 
) throws CertPathValidatorException
inlinestatic

Requests certificate revocation status using OCSP.

引数
certthe certificate to be checked
issuerCertificateThe issuer certificate
responderURIan address of OCSP responder. Overrides any OCSP responder URIs stored in certificate's AIA extension
date
responderCerta certificate that OCSP responder uses to sign OCSP responses
戻り値
revocation status
102  {
103  if (cert == null)
104  throw new IllegalArgumentException("cert cannot be null");
105  if (issuerCertificate == null)
106  throw new IllegalArgumentException("issuerCertificate cannot be null");
107  if (responderURI == null)
108  throw new IllegalArgumentException("responderURI cannot be null");
109 
110  return check(cert, issuerCertificate, Collections.singletonList(responderURI), responderCert, date);
111  }
static OCSPRevocationStatus check(X509Certificate cert, X509Certificate issuerCertificate, URI responderURI, X509Certificate responderCert, Date date)
Definition: OCSPUtils.java:102

◆ check() [2/4]

static OCSPRevocationStatus org.keycloak.common.util.OCSPUtils.check ( X509Certificate  cert,
X509Certificate  issuerCertificate,
Date  date,
X509Certificate  responderCert 
) throws CertPathValidatorException
inlinestatic

Requests certificate revocation status using OCSP. The OCSP responder URI is obtained from the certificate's AIA extension.

引数
certthe certificate to be checked
issuerCertificateThe issuer certificate
date
戻り値
revocation status
120  {
121  List<String> responderURIs = null;
122  try {
123  responderURIs = getResponderURIs(cert);
124  } catch (CertificateEncodingException e) {
125  logger.log(Level.FINE, "CertificateEncodingException: {0}", e.getMessage());
126  throw new CertPathValidatorException(e.getMessage(), e);
127  }
128  if (responderURIs.size() == 0) {
129  logger.log(Level.INFO, "No OCSP responders in the specified certificate");
130  throw new CertPathValidatorException("No OCSP Responder URI in certificate");
131  }
132 
133  List<URI> uris = new LinkedList<>();
134  for (String value : responderURIs) {
135  try {
136  URI responderURI = URI.create(value);
137  uris.add(responderURI);
138  } catch (IllegalArgumentException ex) {
139  logger.log(Level.FINE, "Malformed responder URI {0}", value);
140  }
141  }
142  return check(cert, issuerCertificate, Collections.unmodifiableList(uris), responderCert, date);
143  }
static final Logger logger
Definition: OCSPUtils.java:76
static OCSPRevocationStatus check(X509Certificate cert, X509Certificate issuerCertificate, URI responderURI, X509Certificate responderCert, Date date)
Definition: OCSPUtils.java:102
static List< String > getResponderURIs(X509Certificate cert)
Definition: OCSPUtils.java:545

◆ check() [3/4]

static OCSPRevocationStatus org.keycloak.common.util.OCSPUtils.check ( X509Certificate  cert,
X509Certificate  issuerCertificate 
) throws CertPathValidatorException
inlinestatic

Requests certificate revocation status using OCSP. The OCSP responder URI is obtained from the certificate's AIA extension.

引数
certthe certificate to be checked
issuerCertificateThe issuer certificate
戻り値
revocation status
151  {
152  return check(cert, issuerCertificate, null, null);
153  }
static OCSPRevocationStatus check(X509Certificate cert, X509Certificate issuerCertificate, URI responderURI, X509Certificate responderCert, Date date)
Definition: OCSPUtils.java:102

◆ check() [4/4]

static OCSPRevocationStatus org.keycloak.common.util.OCSPUtils.check ( X509Certificate  cert,
X509Certificate  issuerCertificate,
List< URI >  responderURIs,
X509Certificate  responderCert,
Date  date 
) throws CertPathValidatorException
inlinestaticprivate

Requests certificate revocation status using OCSP.

引数
certthe certificate to be checked
issuerCertificatethe issuer certificate
responderURIsthe OCSP responder URIs
responderCertthe OCSP responder certificate
dateif null, the current time is used.
戻り値
a revocation status
例外
CertPathValidatorException
216  {
217  if (responderURIs == null || responderURIs.size() == 0)
218  throw new IllegalArgumentException("Need at least one responder");
219  try {
220  DigestCalculator digCalc = new BcDigestCalculatorProvider()
221  .get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1));
222 
223  JcaCertificateID certificateID = new JcaCertificateID(digCalc, issuerCertificate, cert.getSerialNumber());
224 
225  // Create a nounce extension to protect against replay attacks
226  SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
227  BigInteger nounce = BigInteger.valueOf(Math.abs(random.nextInt()));
228 
229  DEROctetString derString = new DEROctetString(nounce.toByteArray());
230  Extension nounceExtension = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, false, derString);
231  Extensions extensions = new Extensions(nounceExtension);
232 
233  OCSPReq ocspReq = new OCSPReqBuilder().addRequest(certificateID, extensions).build();
234 
235  URI responderURI = responderURIs.get(0);
236  logger.log(Level.INFO, "OCSP Responder {0}", responderURI);
237 
238  try {
239  OCSPResp resp = getResponse(ocspReq, responderURI);
240  logger.log(Level.FINE, "Received a response from OCSP responder {0}, the response status is {1}", new Object[]{responderURI, resp.getStatus()});
241  switch (resp.getStatus()) {
242  case OCSPResp.SUCCESSFUL:
243  if (resp.getResponseObject() instanceof BasicOCSPResp) {
244  return processBasicOCSPResponse(issuerCertificate, responderCert, date, certificateID, nounce, (BasicOCSPResp)resp.getResponseObject());
245  } else {
246  throw new CertPathValidatorException("OCSP responder returned an invalid or unknown OCSP response.");
247  }
248 
249  case OCSPResp.INTERNAL_ERROR:
250  case OCSPResp.TRY_LATER:
251  throw new CertPathValidatorException("Internal error/try later. OCSP response error: " + resp.getStatus(), (Throwable) null, (CertPath) null, -1, CertPathValidatorException.BasicReason.UNDETERMINED_REVOCATION_STATUS);
252 
253  case OCSPResp.SIG_REQUIRED:
254  throw new CertPathValidatorException("Invalid or missing signature. OCSP response error: " + resp.getStatus(), (Throwable) null, (CertPath) null, -1, CertPathValidatorException.BasicReason.INVALID_SIGNATURE);
255 
256  case OCSPResp.UNAUTHORIZED:
257  throw new CertPathValidatorException("Unauthorized request. OCSP response error: " + resp.getStatus(), (Throwable) null, (CertPath) null, -1, CertPathValidatorException.BasicReason.UNSPECIFIED);
258 
259  case OCSPResp.MALFORMED_REQUEST:
260  default:
261  throw new CertPathValidatorException("OCSP request is malformed. OCSP response error: " + resp.getStatus(), (Throwable) null, (CertPath) null, -1, CertPathValidatorException.BasicReason.UNSPECIFIED);
262  }
263  }
264  catch(IOException e) {
265  logger.log(Level.FINE, "OCSP Responder \"{0}\" failed to return a valid OCSP response\n{1}",
266  new Object[] {responderURI, e.getMessage()});
267  throw new CertPathValidatorException("OCSP check failed", e);
268  }
269  }
270  catch(CertificateNotYetValidException | CertificateExpiredException | OperatorCreationException | OCSPException | CertificateEncodingException | NoSuchAlgorithmException | NoSuchProviderException e) {
271  logger.log(Level.FINE, e.getMessage());
272  throw new CertPathValidatorException(e.getMessage(), e);
273  }
274  }
static OCSPResp getResponse(OCSPReq ocspReq, URI responderUri)
Definition: OCSPUtils.java:155
static OCSPRevocationStatus processBasicOCSPResponse(X509Certificate issuerCertificate, X509Certificate responderCertificate, Date date, JcaCertificateID certificateID, BigInteger nounce, BasicOCSPResp basicOcspResponse)
Definition: OCSPUtils.java:276
static final Logger logger
Definition: OCSPUtils.java:76

◆ compareCertIDs()

static boolean org.keycloak.common.util.OCSPUtils.compareCertIDs ( JcaCertificateID  idLeft,
CertificateID  idRight 
)
inlinestaticprivate
294  {
295  if (idLeft == idRight)
296  return true;
297  if (idLeft == null || idRight == null)
298  return false;
299 
300  return Arrays.equals(idLeft.getIssuerKeyHash(), idRight.getIssuerKeyHash()) &&
301  Arrays.equals(idLeft.getIssuerNameHash(), idRight.getIssuerNameHash()) &&
302  idLeft.getSerialNumber().equals(idRight.getSerialNumber());
303  }

◆ getResponderURIs()

static List<String> org.keycloak.common.util.OCSPUtils.getResponderURIs ( X509Certificate  cert) throws CertificateEncodingException
inlinestaticprivate

Extracts OCSP responder URI from X509 AIA v3 extension, if available. There can be multiple responder URIs encoded in the certificate.

引数
cert
戻り値
a list of available responder URIs.
例外
CertificateEncodingException
545  {
546 
547  LinkedList<String> responderURIs = new LinkedList<>();
548  JcaX509CertificateHolder holder = new JcaX509CertificateHolder(cert);
549  Extension aia = holder.getExtension(Extension.authorityInfoAccess);
550  if (aia != null) {
551  try {
552  ASN1InputStream in = new ASN1InputStream(aia.getExtnValue().getOctetStream());
553  ASN1Sequence seq = (ASN1Sequence)in.readObject();
554  AuthorityInformationAccess authorityInfoAccess = AuthorityInformationAccess.getInstance(seq);
555  for (AccessDescription ad : authorityInfoAccess.getAccessDescriptions()) {
556  if (ad.getAccessMethod().equals(AccessDescription.id_ad_ocsp)) {
557  // See https://www.ietf.org/rfc/rfc2560.txt, 3.1 Certificate Content
558  if (ad.getAccessLocation().getTagNo() == GeneralName.uniformResourceIdentifier) {
559  DERIA5String value = DERIA5String.getInstance(ad.getAccessLocation().getName());
560  responderURIs.add(value.getString());
561  }
562  }
563  }
564  } catch (IOException e) {
565  e.printStackTrace();
566  }
567  }
568  return responderURIs;
569  }

◆ getResponse()

static OCSPResp org.keycloak.common.util.OCSPUtils.getResponse ( OCSPReq  ocspReq,
URI  responderUri 
) throws IOException
inlinestaticprivate
155  {
156  DataOutputStream dataOut = null;
157  InputStream in = null;
158  try {
159  byte[] array = ocspReq.getEncoded();
160  URL urlt = responderUri.toURL();
161  HttpURLConnection con = (HttpURLConnection) urlt.openConnection();
162  con.setRequestMethod("POST");
163  con.setConnectTimeout(OCSP_CONNECT_TIMEOUT);
164  con.setReadTimeout(OCSP_CONNECT_TIMEOUT);
165  con.setRequestProperty("Content-type", "application/ocsp-request");
166  con.setRequestProperty("Content-length", String.valueOf(array.length));
167 // con.setRequestProperty("Accept", "application/ocsp-response");
168 
169  con.setDoOutput(true);
170  con.setDoInput(true);
171  OutputStream out = con.getOutputStream();
172  dataOut = new DataOutputStream(new BufferedOutputStream(out));
173  dataOut.write(array);
174  dataOut.flush();
175 
176  if (con.getResponseCode() / 100 != 2) {
177  String errorMessage = String.format("Connection error, unable to obtain certificate revocation status using OCSP responder \"%s\", code \"%d\"",
178  responderUri.toString(), con.getResponseCode());
179  throw new IOException(errorMessage);
180  }
181  //Get Response
182  in = (InputStream) con.getInputStream();
183  int contentLen = con.getContentLength();
184  if (contentLen == -1) {
185  contentLen = Integer.MAX_VALUE;
186  }
187  ByteArrayOutputStream baos = new ByteArrayOutputStream();
188  int bytesRead = 0;
189  byte[] buffer = new byte[2048];
190  while ((bytesRead = in.read(buffer, 0, buffer.length)) >= 0) {
191  baos.write(buffer, 0, bytesRead);
192  }
193  baos.flush();
194  byte[] data = baos.toByteArray();
195  return new OCSPResp(data);
196  } finally {
197  if (dataOut != null) {
198  dataOut.close();
199  }
200  if (in != null) {
201  in.close();
202  }
203  }
204  }
static int OCSP_CONNECT_TIMEOUT
Definition: OCSPUtils.java:78

◆ processBasicOCSPResponse()

static OCSPRevocationStatus org.keycloak.common.util.OCSPUtils.processBasicOCSPResponse ( X509Certificate  issuerCertificate,
X509Certificate  responderCertificate,
Date  date,
JcaCertificateID  certificateID,
BigInteger  nounce,
BasicOCSPResp  basicOcspResponse 
) throws OCSPException, NoSuchProviderException, NoSuchAlgorithmException, CertificateNotYetValidException, CertificateExpiredException, CertPathValidatorException
inlinestaticprivate
277  {
278  SingleResp expectedResponse = null;
279  for (SingleResp singleResponse : basicOcspResponse.getResponses()) {
280  if (compareCertIDs(certificateID, singleResponse.getCertID())) {
281  expectedResponse = singleResponse;
282  break;
283  }
284  }
285 
286  if (expectedResponse != null) {
287  verifyResponse(basicOcspResponse, issuerCertificate, responderCertificate, nounce.toByteArray(), date);
288  return singleResponseToRevocationStatus(expectedResponse);
289  } else {
290  throw new CertPathValidatorException("OCSP response does not include a response for a certificate supplied in the OCSP request");
291  }
292  }
static void verifyResponse(BasicOCSPResp basicOcspResponse, X509Certificate issuerCertificate, X509Certificate responderCertificate, byte[] requestNonce, Date date)
Definition: OCSPUtils.java:305
static OCSPRevocationStatus singleResponseToRevocationStatus(final SingleResp singleResponse)
Definition: OCSPUtils.java:495
static boolean compareCertIDs(JcaCertificateID idLeft, CertificateID idRight)
Definition: OCSPUtils.java:294

◆ singleResponseToRevocationStatus()

static OCSPRevocationStatus org.keycloak.common.util.OCSPUtils.singleResponseToRevocationStatus ( final SingleResp  singleResponse) throws CertPathValidatorException
inlinestaticprivate
495  {
496  final CertificateStatus certStatus = singleResponse.getCertStatus();
497 
498  int revocationReason = CRLReason.unspecified;
499  Date revocationTime = null;
500  RevocationStatus status = RevocationStatus.UNKNOWN;
501  if (certStatus == CertificateStatus.GOOD) {
502  status = RevocationStatus.GOOD;
503  } else if (certStatus instanceof RevokedStatus) {
504  RevokedStatus revoked = (RevokedStatus)certStatus;
505  revocationTime = revoked.getRevocationTime();
506  status = RevocationStatus.REVOKED;
507  if (revoked.hasRevocationReason()) {
508  revocationReason = revoked.getRevocationReason();
509  }
510  } else if (certStatus instanceof UnknownStatus) {
511  status = RevocationStatus.UNKNOWN;
512  } else {
513  throw new CertPathValidatorException("Unrecognized revocation status received from OCSP.");
514  }
515 
516  final RevocationStatus finalStatus = status;
517  final Date finalRevocationTime = revocationTime;
518  final int finalRevocationReason = revocationReason;
519  return new OCSPRevocationStatus() {
520  @Override
521  public RevocationStatus getRevocationStatus() {
522  return finalStatus;
523  }
524 
525  @Override
526  public Date getRevocationTime() {
527  return finalRevocationTime;
528  }
529 
530  @Override
531  public CRLReason getRevocationReason() {
532  return CRLReason.lookup(finalRevocationReason);
533  }
534  };
535  }

◆ unknownStatus()

static OCSPRevocationStatus org.keycloak.common.util.OCSPUtils.unknownStatus ( )
inlinestaticprivate
476  {
477  return new OCSPRevocationStatus() {
478  @Override
479  public RevocationStatus getRevocationStatus() {
480  return RevocationStatus.UNKNOWN;
481  }
482 
483  @Override
484  public Date getRevocationTime() {
485  return new Date(System.currentTimeMillis());
486  }
487 
488  @Override
489  public CRLReason getRevocationReason() {
490  return CRLReason.lookup(CRLReason.unspecified);
491  }
492  };
493  }

◆ verifyResponse()

static void org.keycloak.common.util.OCSPUtils.verifyResponse ( BasicOCSPResp  basicOcspResponse,
X509Certificate  issuerCertificate,
X509Certificate  responderCertificate,
byte []  requestNonce,
Date  date 
) throws NoSuchProviderException, NoSuchAlgorithmException, CertificateNotYetValidException, CertificateExpiredException, CertPathValidatorException
inlinestaticprivate
305  {
306 
307  List<X509CertificateHolder> certs = new ArrayList<>(Arrays.asList(basicOcspResponse.getCerts()));
308  X509Certificate signingCert = null;
309 
310  try {
311  certs.add(new JcaX509CertificateHolder(issuerCertificate));
312  if (responderCertificate != null) {
313  certs.add(new JcaX509CertificateHolder(responderCertificate));
314  }
315  } catch (CertificateEncodingException e) {
316  e.printStackTrace();
317  }
318  if (certs.size() > 0) {
319 
320  X500Name responderName = basicOcspResponse.getResponderId().toASN1Primitive().getName();
321  byte[] responderKey = basicOcspResponse.getResponderId().toASN1Primitive().getKeyHash();
322 
323  if (responderName != null) {
324  logger.log(Level.INFO, "Responder Name: {0}", responderName.toString());
325  for (X509CertificateHolder certHolder : certs) {
326  try {
327  X509Certificate tempCert = new JcaX509CertificateConverter()
328  .setProvider("BC").getCertificate(certHolder);
329  X500Name respName = new X500Name(tempCert.getSubjectX500Principal().getName());
330  if (responderName.equals(respName)) {
331  signingCert = tempCert;
332  logger.log(Level.INFO, "Found a certificate whose principal \"{0}\" matches the responder name \"{1}\"",
333  new Object[] {tempCert.getSubjectDN().getName(), responderName.toString()});
334  break;
335  }
336  } catch (CertificateException e) {
337  logger.log(Level.FINE, e.getMessage());
338  }
339  }
340  } else if (responderKey != null) {
341  SubjectKeyIdentifier responderSubjectKey = new SubjectKeyIdentifier(responderKey);
342  logger.log(Level.INFO, "Responder Key: {0}", Arrays.toString(responderKey));
343  for (X509CertificateHolder certHolder : certs) {
344  try {
345  X509Certificate tempCert = new JcaX509CertificateConverter()
346  .setProvider("BC").getCertificate(certHolder);
347 
348  SubjectKeyIdentifier subjectKeyIdentifier = null;
349  if (certHolder.getExtensions() != null) {
350  subjectKeyIdentifier = SubjectKeyIdentifier.fromExtensions(certHolder.getExtensions());
351  }
352 
353  if (subjectKeyIdentifier != null) {
354  logger.log(Level.INFO, "Certificate: {0}\nSubject Key Id: {1}",
355  new Object[] {tempCert.getSubjectDN().getName(), Arrays.toString(subjectKeyIdentifier.getKeyIdentifier())});
356  }
357 
358  if (subjectKeyIdentifier != null && responderSubjectKey.equals(subjectKeyIdentifier)) {
359  signingCert = tempCert;
360  logger.log(Level.INFO, "Found a signer certificate \"{0}\" with the subject key extension value matching the responder key",
361  signingCert.getSubjectDN().getName());
362 
363  break;
364  }
365 
366  subjectKeyIdentifier = new JcaX509ExtensionUtils().createSubjectKeyIdentifier(tempCert.getPublicKey());
367  if (responderSubjectKey.equals(subjectKeyIdentifier)) {
368  signingCert = tempCert;
369  logger.log(Level.INFO, "Found a certificate \"{0}\" with the subject key matching the OCSP responder key", signingCert.getSubjectDN().getName());
370  break;
371  }
372 
373  } catch (CertificateException e) {
374  logger.log(Level.FINE, e.getMessage());
375  }
376  }
377  }
378  }
379  if (signingCert != null) {
380  if (signingCert.equals(issuerCertificate)) {
381  logger.log(Level.INFO, "OCSP response is signed by the target\'s Issuing CA");
382  } else if (responderCertificate != null && signingCert.equals(responderCertificate)) {
383  // https://www.ietf.org/rfc/rfc2560.txt
384  // 2.6 OCSP Signature Authority Delegation
385  // - The responder certificate is issued to the responder by CA
386  logger.log(Level.INFO, "OCSP response is signed by an authorized responder certificate");
387  } else {
388  // 4.2.2.2 Authorized Responders
389  // 3. Includes a value of id-ad-ocspSigning in an ExtendedKeyUsage
390  // extension and is issued by the CA that issued the certificate in
391  // question."
392  if (!signingCert.getIssuerX500Principal().equals(issuerCertificate.getSubjectX500Principal())) {
393  logger.log(Level.INFO, "Signer certificate's Issuer: {0}\nIssuer certificate's Subject: {1}",
394  new Object[] {signingCert.getIssuerX500Principal().getName(), issuerCertificate.getSubjectX500Principal().getName()});
395  throw new CertPathValidatorException("Responder\'s certificate is not authorized to sign OCSP responses");
396  }
397  try {
398  List<String> purposes = signingCert.getExtendedKeyUsage();
399  if (purposes != null && !purposes.contains(KeyPurposeId.id_kp_OCSPSigning.getId())) {
400  logger.log(Level.INFO, "OCSPSigning extended usage is not set");
401  throw new CertPathValidatorException("Responder\'s certificate not valid for signing OCSP responses");
402  }
403  } catch (CertificateParsingException e) {
404  logger.log(Level.FINE, "Failed to get certificate's extended key usage extension\n{0}", e.getMessage());
405  }
406  if (date == null) {
407  signingCert.checkValidity();
408  } else {
409  signingCert.checkValidity(date);
410  }
411  try {
412  Extension noOCSPCheck = new JcaX509CertificateHolder(signingCert).getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck);
413  // TODO If the extension is present, the OCSP client can trust the
414  // responder's certificate for the lifetime of the certificate.
415  logger.log(Level.INFO, "OCSP no-check extension is {0} present", noOCSPCheck == null ? "not" : "");
416  } catch (CertificateEncodingException e) {
417  logger.log(Level.FINE, "Certificate encoding exception: {0}", e.getMessage());
418  }
419 
420  try {
421  signingCert.verify(issuerCertificate.getPublicKey());
422  logger.log(Level.INFO, "OCSP response is signed by an Authorized Responder");
423 
424  } catch (GeneralSecurityException ex) {
425  signingCert = null;
426  }
427  }
428  }
429  if (signingCert == null) {
430  throw new CertPathValidatorException("Unable to verify OCSP Response\'s signature");
431  } else {
432  if (!verifySignature(basicOcspResponse, signingCert)) {
433  throw new CertPathValidatorException("Error verifying OCSP Response\'s signature");
434  } else {
435  Extension responseNonce = basicOcspResponse.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce);
436  if (responseNonce != null && requestNonce != null && !Arrays.equals(requestNonce, responseNonce.getExtnValue().getOctets())) {
437  throw new CertPathValidatorException("Nonces do not match.");
438  } else {
439  // See Sun's OCSP implementation.
440  // https://www.ietf.org/rfc/rfc2560.txt, if nextUpdate is not set,
441  // the responder is indicating that newer update is avilable all the time
442  long current = date == null ? System.currentTimeMillis() : date.getTime();
443  Date stop = new Date(current + (long) TIME_SKEW);
444  Date start = new Date(current - (long) TIME_SKEW);
445 
446  Iterator<SingleResp> iter = Arrays.asList(basicOcspResponse.getResponses()).iterator();
447  SingleResp singleRes = null;
448  do {
449  if (!iter.hasNext()) {
450  return;
451  }
452  singleRes = iter.next();
453  }
454  while (!stop.before(singleRes.getThisUpdate()) &&
455  !start.after(singleRes.getNextUpdate() != null ? singleRes.getNextUpdate() : singleRes.getThisUpdate()));
456 
457  throw new CertPathValidatorException("Response is unreliable: its validity interval is out-of-date");
458  }
459  }
460  }
461  }
static final Logger logger
Definition: OCSPUtils.java:76
static boolean verifySignature(BasicOCSPResp basicOcspResponse, X509Certificate cert)
Definition: OCSPUtils.java:463
static final int TIME_SKEW
Definition: OCSPUtils.java:79

◆ verifySignature()

static boolean org.keycloak.common.util.OCSPUtils.verifySignature ( BasicOCSPResp  basicOcspResponse,
X509Certificate  cert 
)
inlinestaticprivate
463  {
464  try {
465  ContentVerifierProvider contentVerifier = new JcaContentVerifierProviderBuilder()
466  .setProvider("BC").build(cert.getPublicKey());
467  return basicOcspResponse.isSignatureValid(contentVerifier);
468  } catch (OperatorCreationException e) {
469  logger.log(Level.FINE, "Unable to construct OCSP content signature verifier\n{0}", e.getMessage());
470  } catch (OCSPException e) {
471  logger.log(Level.FINE, "Unable to validate OCSP response signature\n{0}", e.getMessage());
472  }
473  return false;
474  }
static final Logger logger
Definition: OCSPUtils.java:76

メンバ詳解

◆ logger

final Logger org.keycloak.common.util.OCSPUtils.logger = Logger.getLogger(""+OCSPUtils.class)
staticprivate

◆ OCSP_CONNECT_TIMEOUT

int org.keycloak.common.util.OCSPUtils.OCSP_CONNECT_TIMEOUT = 10000
staticprivate

◆ TIME_SKEW

final int org.keycloak.common.util.OCSPUtils.TIME_SKEW = 900000
staticprivate

このクラス詳解は次のファイルから抽出されました: