ocspresponse.java
来自「This is a resource based on j2me embedde」· Java 代码 · 共 731 行 · 第 1/2 页
JAVA
731 行
boolean usedCertFromResponse = false; if (x509Certs != null && x509Certs[0] != null) { /* * If there is a certificate specified in the response having * "OCSP Signing" in the extended key usages field, we verify * it first and if it is trusted then use it to verify the * signature on the OCSP response. */ X509Certificate certFromResponse = null; for (int i = 0; i < x509Certs.length; i++) { int extKeyUsage = x509Certs[i].getExtKeyUsage(); if (extKeyUsage != -1 && (extKeyUsage & X509Certificate.OCSP_EXT_KEY_USAGE) == extKeyUsage) { certFromResponse = x509Certs[i]; break; } } if (certFromResponse != null) { /* * Check whether the cert returned by the responder * is trusted. */ Vector respCertVector = new Vector(1); respCertVector.addElement(certFromResponse); try { /* * Check if the key used to sign the response * is issued by known CA. */ X509Certificate.verifyChain(respCertVector, X509Certificate.DIGITAL_SIG_KEY_USAGE, X509Certificate.OCSP_EXT_KEY_USAGE, keyStore, null); /* * When checking the signature, use the certificate * from the response first. */ certs.insertElementAt(x509Certs[0], 0); usedCertFromResponse = true; } catch (CertificateException ce) { /* * The key used to sign the response can belong to * the CA who issued the certificate in question. */ respCertVector.addElement(issuerCert); try { X509Certificate.verifyChain(respCertVector, X509Certificate.DIGITAL_SIG_KEY_USAGE, X509Certificate.OCSP_EXT_KEY_USAGE, keyStore, null); certs.insertElementAt(x509Certs[0], 0); usedCertFromResponse = true; } catch (CertificateException cex) { // ignore, don't use the certificate from the resp. } } } } if (certs != null) { // Confirm that the signed response was generated using // the public key from the trusted cert boolean verified = false; for (int i = 0; (!verified) && (i < certs.size()); i++) { try { X509Certificate currCert = (X509Certificate)certs.elementAt(i); verified = verifyResponse(responseDataDer, currCert.getPublicKey(), sigAlgId, signature); } catch (SignatureException e) { /* * IMPL_NOTE: if the key usage does not include * KP_OCSP_SIGNING_OID then SignatureException * is thrown. We should check the key usages first * and remove this try-catch, but certificates * in certs vector don't contain this information. */ verified = false; } } if (usedCertFromResponse) { /* * Remove the certificate we've previously added to certs * to prevent modification of the vector passed as a * parameter to this function. */ certs.removeElementAt(0); } if (!verified) { if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY, "Error verifying OCSP Responder's signature"); } throw new OCSPException( OCSPException.CANNOT_VERIFY_SIGNATURE, "Error verifying OCSP Responder's signature"); } } else { // Need responder's cert in order to verify the signature if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY, "Unable to verify OCSP Responder's signature"); } throw new OCSPException(OCSPException.CANNOT_VERIFY_SIGNATURE, "Unable to verify OCSP Responder's signature"); } } catch (OCSPException e) { // e.printStackTrace(); throw e; } catch (Exception e) { throw new OCSPException(OCSPException.UNKNOWN_ERROR, e.getMessage()); } } private String parsex500Name(DerInputStream in) throws IOException { /* * X.500 names are a "SEQUENCE OF" RDNs, which means zero or * more and order matters. We scan them in order, which * conventionally is big-endian. */ DerValue[] nameseq = null; byte[] derBytes = in.toByteArray(); try { nameseq = in.getSequence(5); } catch (IOException ioe) { if (derBytes == null) { nameseq = null; } else { DerValue derVal = new DerValue(DerValue.tag_Sequence, derBytes); derBytes = derVal.toByteArray(); nameseq = new DerInputStream(derBytes).getSequence(5); } } if (nameseq == null) { return null; } else { StringBuffer sb = new StringBuffer(); for (int i = 0; i < nameseq.length; i++) { if (nameseq[i].tag != DerValue.tag_Set) { throw new IOException("X500 RDN"); } DerInputStream dis = new DerInputStream(nameseq[i].toByteArray()); DerValue[] avaset = dis.getSet(5); for (int j = 0; j < avaset.length; j++) { // Individual attribute value assertions are SEQUENCE of two values. // That'd be a "struct" outside of ASN.1. if (avaset[j].tag != DerValue.tag_Sequence) { throw new IOException("AVA not a sequence"); } if (j != 0) { sb.append(" + "); } sb.append(avaset[j].data.getOID().toString()); sb.append(avaset[j].data.getDerValue().getAsString()); if (avaset[j].data.available() != 0) { throw new IOException("AVA, extra bytes = " + avaset[j].data.available()); } } sb.append(";"); } return sb.toString(); } } /* * Verify the signature of the OCSP response. * The responder's cert is implicitly trusted. */ private boolean verifyResponse(byte[] responseData, PublicKey pubKey, AlgorithmId sigAlgId, byte[] signBytes) throws SignatureException, CertificateException { try { Signature respSignature = Signature.getInstance(sigAlgId.getName()); respSignature.initVerify(pubKey); respSignature.update(responseData, 0, responseData.length); if (respSignature.verify(signBytes)) { if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY, "Verified signature of OCSP Responder"); } return true; } else { if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY, "Error verifying signature of OCSP Responder"); } return false; } } catch (InvalidKeyException ike) { throw new SignatureException("Invalid key: " + ike.getMessage()); } catch (NoSuchAlgorithmException nsae) { throw new SignatureException("Invalid algorithm: " + nsae.getMessage()); } } /* * Return the revocation status code for a given certificate. */ // used by OCSPValidatorImpl int getCertStatus() { return singleResponse.getStatus(); } // used by OCSPValidatorImpl CertId getCertId() { return singleResponse.getCertId(); } /* * Map a certificate's revocation status code to a string. */ // used by OCSPValidatorImpl static String certStatusToText(int certStatus) { switch (certStatus) { case CertStatus.GOOD: return "Good"; case CertStatus.REVOKED: return "Revoked"; case CertStatus.UNKNOWN: return "Unknown"; default: return ("Unknown certificate status code: " + certStatus); } } /* * A class representing a single OCSP response. */ private class SingleResponse { private CertId certId; private int certStatus; private Date thisUpdate; private Date nextUpdate; private SingleResponse(DerValue der) throws IOException { if (der.tag != DerValue.tag_Sequence) { throw new IOException("Bad ASN.1 encoding in SingleResponse"); } DerInputStream tmp = der.data; certId = new CertId(tmp.getDerValue().data); DerValue derVal = tmp.getDerValue(); short tag = (byte)(derVal.tag & 0x1f); if (tag == CertStatus.GOOD) { certStatus = CertStatus.GOOD; } else if (tag == CertStatus.REVOKED) { certStatus = CertStatus.REVOKED; // RevokedInfo if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Date revocationTime = derVal.data.getGeneralizedTime(); Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY, "Revocation time: " + revocationTime); } } else if (tag == CertStatus.UNKNOWN) { certStatus = CertStatus.UNKNOWN; } else { throw new IOException("Invalid certificate status: " + tag); } thisUpdate = tmp.getGeneralizedTime(); if (tmp.available() == 0) { // we are done } else { derVal = tmp.getDerValue(); tag = (byte)(derVal.tag & 0x1f); if (tag == 0) { // next update nextUpdate = derVal.data.getGeneralizedTime(); if (tmp.available() == 0) { return; } else { derVal = tmp.getDerValue(); tag = (byte)(derVal.tag & 0x1f); } } // ignore extensions } Date now = new Date(); if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { String until = ""; if (nextUpdate != null) { until = " until " + nextUpdate; } Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY, "Response's validity interval is from " + thisUpdate + until); } // Check that the test date is within the validity interval if ((thisUpdate != null && (now.getTime() < thisUpdate.getTime())) || (nextUpdate != null && (now.getTime() > nextUpdate.getTime()))) { if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY, "Response is unreliable: " + "its validity interval is out-of-date"); } throw new IOException("Response is unreliable: its validity " + "interval is out-of-date"); } } /* * Return the certificate's revocation status code */ private int getStatus() { return certStatus; } private CertId getCertId() { return certId; } /** * Construct a string representation of a single OCSP response. */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append("SingleResponse: \n"); sb.append(certId); sb.append("\nCertStatus: "); sb.append(certStatusToText(getCertStatus())); sb.append("\n"); sb.append("thisUpdate is "); sb.append(thisUpdate); sb.append("\n"); if (nextUpdate != null) { sb.append("nextUpdate is "); sb.append(nextUpdate); sb.append("\n"); } return sb.toString(); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?