public static void main(String[] args) throws Exception { // Generate 20 serial numbers with dup and a special order int count = 20; BigInteger[] serials = new BigInteger[count]; for (int i = 0; i < count; i++) { serials[i] = BigInteger.valueOf(i * 7 % 10); } // Generates a CRL X509CRLEntry[] badCerts = new X509CRLEntry[count]; for (int i = 0; i < count; i++) { badCerts[i] = new X509CRLEntryImpl(serials[i], new Date(System.currentTimeMillis() + i * 1000)); } X500Name owner = new X500Name("CN=CA"); X509CRLImpl crl = new X509CRLImpl(owner, new Date(), new Date(), badCerts); KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); crl.sign(kpg.genKeyPair().getPrivate(), "SHA1withRSA"); byte[] data = crl.getEncodedInternal(); // Check the encoding checkData(crl, data, serials); // Load a CRL from raw data CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509CRLImpl crl2 = (X509CRLImpl) cf.generateCRL(new ByteArrayInputStream(data)); // Check the encoding again data = crl2.getEncodedInternal(); checkData(crl2, data, serials); }
private static void permissionCheck() { SecurityManager sec = System.getSecurityManager(); if (sec != null) { sec.checkPermission(new RuntimePermission("useKeychainStore")); } }
void verify(List<CertId> certIds, X509Certificate responderCert, Date date, byte[] nonce) throws CertPathValidatorException { switch (responseStatus) { case SUCCESSFUL: break; case TRY_LATER: case INTERNAL_ERROR: throw new CertPathValidatorException( "OCSP response error: " + responseStatus, null, null, -1, BasicReason.UNDETERMINED_REVOCATION_STATUS); case UNAUTHORIZED: default: throw new CertPathValidatorException("OCSP response error: " + responseStatus); } // Check that the response includes a response for all of the // certs that were supplied in the request for (CertId certId : certIds) { SingleResponse sr = getSingleResponse(certId); if (sr == null) { if (debug != null) { debug.println("No response found for CertId: " + certId); } throw new CertPathValidatorException( "OCSP response does not include a response for a " + "certificate supplied in the OCSP request"); } if (debug != null) { debug.println( "Status of certificate (with serial number " + certId.getSerialNumber() + ") is: " + sr.getCertStatus()); } } // Check whether the cert returned by the responder is trusted if (!certs.isEmpty()) { X509CertImpl cert = certs.get(0); // First check if the cert matches the expected responder cert if (cert.equals(responderCert)) { // cert is trusted, now verify the signed response // Next check if the cert was issued by the responder cert // which was set locally. } else if (cert.getIssuerX500Principal().equals(responderCert.getSubjectX500Principal())) { // Check for the OCSPSigning key purpose try { List<String> keyPurposes = cert.getExtendedKeyUsage(); if (keyPurposes == null || !keyPurposes.contains(KP_OCSP_SIGNING_OID)) { throw new CertPathValidatorException( "Responder's certificate not valid for signing " + "OCSP responses"); } } catch (CertificateParsingException cpe) { // assume cert is not valid for signing throw new CertPathValidatorException( "Responder's certificate not valid for signing " + "OCSP responses", cpe); } // Check algorithm constraints specified in security property // "jdk.certpath.disabledAlgorithms". AlgorithmChecker algChecker = new AlgorithmChecker(new TrustAnchor(responderCert, null)); algChecker.init(false); algChecker.check(cert, Collections.<String>emptySet()); // check the validity try { if (date == null) { cert.checkValidity(); } else { cert.checkValidity(date); } } catch (CertificateException e) { throw new CertPathValidatorException( "Responder's certificate not within the " + "validity period", e); } // check for revocation // // A CA may specify that an OCSP client can trust a // responder for the lifetime of the responder's // certificate. The CA does so by including the // extension id-pkix-ocsp-nocheck. // Extension noCheck = cert.getExtension(PKIXExtensions.OCSPNoCheck_Id); if (noCheck != null) { if (debug != null) { debug.println( "Responder's certificate includes " + "the extension id-pkix-ocsp-nocheck."); } } else { // we should do the revocation checking of the // authorized responder in a future update. } // verify the signature try { cert.verify(responderCert.getPublicKey()); responderCert = cert; // cert is trusted, now verify the signed response } catch (GeneralSecurityException e) { responderCert = null; } } else { throw new CertPathValidatorException( "Responder's certificate is not authorized to sign " + "OCSP responses"); } } // Confirm that the signed response was generated using the public // key from the trusted responder cert if (responderCert != null) { // Check algorithm constraints specified in security property // "jdk.certpath.disabledAlgorithms". AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId); if (!verifySignature(responderCert)) { throw new CertPathValidatorException("Error verifying OCSP Response's signature"); } } else { // Need responder's cert in order to verify the signature throw new CertPathValidatorException("Unable to verify OCSP Response's signature"); } // Check freshness of OCSPResponse if (nonce != null) { if (responseNonce != null && !Arrays.equals(nonce, responseNonce)) { throw new CertPathValidatorException("Nonces don't match"); } } long now = (date == null) ? System.currentTimeMillis() : date.getTime(); Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW); Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW); for (SingleResponse sr : singleResponseMap.values()) { if (debug != null) { String until = ""; if (sr.nextUpdate != null) { until = " until " + sr.nextUpdate; } debug.println("Response's validity interval is from " + sr.thisUpdate + until); } // Check that the test date is within the validity interval if ((sr.thisUpdate != null && nowPlusSkew.before(sr.thisUpdate)) || (sr.nextUpdate != null && nowMinusSkew.after(sr.nextUpdate))) { throw new CertPathValidatorException( "Response is unreliable: its validity " + "interval is out-of-date"); } } }