/* * Check for a valid certificate pair */ private void checkPair() throws CertificateException { /* if either of pair is missing, return w/o error */ if (forward == null || reverse == null) { return; } /* * If both elements of the pair are present, check that they * are a valid pair. */ X500Principal fwSubject = forward.getSubjectX500Principal(); X500Principal fwIssuer = forward.getIssuerX500Principal(); X500Principal rvSubject = reverse.getSubjectX500Principal(); X500Principal rvIssuer = reverse.getIssuerX500Principal(); if (!fwIssuer.equals(rvSubject) || !rvIssuer.equals(fwSubject)) { throw new CertificateException( "subject and issuer names in " + "forward and reverse certificates do not match"); } /* check signatures unless key parameters are missing */ try { PublicKey pk = reverse.getPublicKey(); if (!(pk instanceof DSAPublicKey) || ((DSAPublicKey) pk).getParams() != null) { forward.verify(pk); } pk = forward.getPublicKey(); if (!(pk instanceof DSAPublicKey) || ((DSAPublicKey) pk).getParams() != null) { reverse.verify(pk); } } catch (GeneralSecurityException e) { throw new CertificateException("invalid signature: " + e.getMessage()); } }
/** * Returns true if the input is an instance of this class and if its value equals the value * contained in this class. This method deviates slightly from the XACML spec in the way that it * handles RDNs with multiple attributeTypeAndValue pairs and some additional canonicalization * steps. This method uses the procedure used by <code> * javax.security.auth.x500.X500Principal.equals()</code>, while the XACML spec uses a slightly * different procedure. In practice, it is expected that this difference will not be noticeable. * For more details, refer to the javadoc for <code>X500Principal.equals()</code> and the XACML * specification. * * @param o the object to compare * @return true if this object and the input represent the same value */ public boolean equals(Object o) { if (!(o instanceof X500NameAttribute)) return false; X500NameAttribute other = (X500NameAttribute) o; return value.equals(other.value); }
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { if (certfile == null) { return null; } else { if (issuers == null || issuers.length == 0) { // Postgres 8.4 and earlier do not send the list of accepted certificate // authorities // to the client. See BUG #5468. We only hope, that our certificate will be accepted. return "user"; } else { // Sending a wrong certificate makes the connection rejected, even, if clientcert=0 // in pg_hba.conf. // therefore we only send our certificate, if the issuer is listed in issuers X509Certificate[] certchain = getCertificateChain("user"); if (certchain == null) { return null; } else { X500Principal ourissuer = certchain[certchain.length - 1].getIssuerX500Principal(); boolean found = false; for (Principal issuer : issuers) { if (ourissuer.equals(issuer)) { found = true; } } return (found ? "user" : null); } } } }
/** * Liefert den Aussteller, insofern ermittelbar. * * @return der Aussteller. Wenn es sich um ein selbstsigniertes Zertifikat handelt, liefert die * Funktion NULL. * @throws Exception */ public Entry getIssuer() throws Exception { if (this.issuer != null || this.issuerChecked) return this.issuer; this.issuerChecked = true; X509Certificate x = this.getCertificate(); X500Principal issuer = x.getIssuerX500Principal(); // brauchmer gar nicht erst anfangen zu suchen if (issuer == null) return null; // selbstsigniert if (issuer.equals(x.getSubjectX500Principal())) return null; byte[] issuerSig = x.getExtensionValue(Extension.authorityKeyIdentifier.getId()); List<Entry> all = this.store.getEntries(); // wenn die Signatur des Ausstellers bekannt ist, suchen wir anhand // der. Das ist die zuverlaessigste Methode. if (issuerSig != null && issuerSig.length > 0) { for (Entry e : all) { if (CHECK_CA && !e.isCA()) continue; // OK, wir haben die Signatur des Ausstellers. Mal schauen, // ob wir sie im Keystore finden. byte[] test = e.getCertificate().getPublicKey().getEncoded(); if (Arrays.equals(issuerSig, test)) { this.issuer = e; return e; // gefunden } } } // Wir haben die Signatur nicht, stimmt vielleicht einen passenden DN? for (Entry e : all) { if (CHECK_CA && !e.isCA()) continue; X500Principal subject = e.getCertificate().getSubjectX500Principal(); if (subject.equals(issuer)) { this.issuer = e; return e; } } // nichts gefunden return null; }
/* * Validate Certificate Chain */ private boolean validateChain(Certificate[] certChain) { for (int i = 0; i < certChain.length - 1; i++) { X500Principal issuerDN = ((X509Certificate) certChain[i]).getIssuerX500Principal(); X500Principal subjectDN = ((X509Certificate) certChain[i + 1]).getSubjectX500Principal(); if (!(issuerDN.equals(subjectDN))) return false; } return true; }
/** * Search the given Set of TrustAnchor's for one that is the issuer of the given X509 certificate. * Uses the specified provider for signature verification, or the default provider if null. * * @param cert the X509 certificate * @param trustAnchors a Set of TrustAnchor's * @param sigProvider the provider to use for signature verification * @return the <code>TrustAnchor</code> object if found or <code>null</code> if not. * @throws AnnotatedException if a TrustAnchor was found but the signature verification on the * given certificate has thrown an exception. */ protected static TrustAnchor findTrustAnchor( X509Certificate cert, Set trustAnchors, String sigProvider) throws AnnotatedException { TrustAnchor trust = null; PublicKey trustPublicKey = null; Exception invalidKeyEx = null; X509CertSelector certSelectX509 = new X509CertSelector(); X500Principal certIssuer = getEncodedIssuerPrincipal(cert); try { certSelectX509.setSubject(certIssuer.getEncoded()); } catch (IOException ex) { throw new AnnotatedException("Cannot set subject search criteria for trust anchor.", ex); } Iterator iter = trustAnchors.iterator(); while (iter.hasNext() && trust == null) { trust = (TrustAnchor) iter.next(); if (trust.getTrustedCert() != null) { if (certSelectX509.match(trust.getTrustedCert())) { trustPublicKey = trust.getTrustedCert().getPublicKey(); } else { trust = null; } } else if (trust.getCAName() != null && trust.getCAPublicKey() != null) { try { X500Principal caName = new X500Principal(trust.getCAName()); if (certIssuer.equals(caName)) { trustPublicKey = trust.getCAPublicKey(); } else { trust = null; } } catch (IllegalArgumentException ex) { trust = null; } } else { trust = null; } if (trustPublicKey != null) { try { verifyX509Certificate(cert, trustPublicKey, sigProvider); } catch (Exception ex) { invalidKeyEx = ex; trust = null; trustPublicKey = null; } } } if (trust == null && invalidKeyEx != null) { throw new AnnotatedException( "TrustAnchor found but certificate validation failed.", invalidKeyEx); } return trust; }
/** * Liefert alle Schluessel, die von diesem signiert wurden. * * @return Liste aller Schluessel, die von diesem signiert wurden. Die Funktion liefert nie NULL * sondern hoechstens eine leere Liste. * @throws Exception */ public List<Entry> getClients() throws Exception { if (this.clients != null) return this.clients; this.clients = new ArrayList<Entry>(); if (CHECK_CA && !this.isCA()) return this.clients; X509Certificate x = this.getCertificate(); byte[] sig = x.getPublicKey().getEncoded(); X500Principal self = x.getSubjectX500Principal(); // 2. Wir sind ein CA-Zertifikat, jetzt holen wir alle // Zertifikate, bei denen wir als CA eingetragen sind. List<Entry> all = this.store.getEntries(); for (Entry e : all) { X509Certificate c = e.getCertificate(); // sind wir selbst if (c.equals(x)) continue; // Checken, ob die Aussteller-Signatur angegeben ist byte[] issuerSig = x.getExtensionValue(Extension.authorityKeyIdentifier.getId()); if (issuerSig != null && issuerSig.length > 0) { // Issuer-Signatur angegeben. Mal checken, ob es unsere ist if (Arrays.equals(issuerSig, sig)) { // jepp, passt this.clients.add(e); continue; } } // Checken, ob der DN uebereinstimmt. X500Principal p = c.getIssuerX500Principal(); // passt, nehmen wir auch if (p != null && p.equals(self)) { this.clients.add(e); continue; } } Collections.sort(this.clients); return this.clients; }
/** @param certs */ private List sortCerts(List certs) { if (certs.size() < 2) { return certs; } X500Principal issuer = ((X509Certificate) certs.get(0)).getIssuerX500Principal(); boolean okay = true; for (int i = 1; i != certs.size(); i++) { X509Certificate cert = (X509Certificate) certs.get(i); if (issuer.equals(cert.getSubjectX500Principal())) { issuer = ((X509Certificate) certs.get(i)).getIssuerX500Principal(); } else { okay = false; break; } } if (okay) { return certs; } // find end-entity cert List retList = new ArrayList(certs.size()); List orig = new ArrayList(certs); for (int i = 0; i < certs.size(); i++) { X509Certificate cert = (X509Certificate) certs.get(i); boolean found = false; X500Principal subject = cert.getSubjectX500Principal(); for (int j = 0; j != certs.size(); j++) { X509Certificate c = (X509Certificate) certs.get(j); if (c.getIssuerX500Principal().equals(subject)) { found = true; break; } } if (!found) { retList.add(cert); certs.remove(i); } } // can only have one end entity cert - something's wrong, give up. if (retList.size() > 1) { return orig; } for (int i = 0; i != retList.size(); i++) { issuer = ((X509Certificate) retList.get(i)).getIssuerX500Principal(); for (int j = 0; j < certs.size(); j++) { X509Certificate c = (X509Certificate) certs.get(j); if (issuer.equals(c.getSubjectX500Principal())) { retList.add(c); certs.remove(j); break; } } } // make sure all certificates are accounted for. if (certs.size() > 0) { return orig; } return retList; }
X509Certificate[] engineValidate(X509Certificate[] chain, Collection otherCerts, Object parameter) throws CertificateException { if ((chain == null) || (chain.length == 0)) { throw new CertificateException("null or zero-length certificate chain"); } if (TRY_VALIDATOR) { // check that chain is in correct order and check if chain contains // trust anchor X500Principal prevIssuer = null; for (int i = 0; i < chain.length; i++) { X509Certificate cert = chain[i]; X500Principal dn = cert.getSubjectX500Principal(); if (i != 0 && !dn.equals(prevIssuer)) { // chain is not ordered correctly, call builder instead return doBuild(chain, otherCerts); } // Check if chain[i] is already trusted. It may be inside // trustedCerts, or has the same dn and public key as a cert // inside trustedCerts. The latter happens when a CA has // updated its cert with a stronger signature algorithm in JRE // but the weak one is still in circulation. if (trustedCerts.contains(cert) || // trusted cert (trustedSubjects.containsKey(dn) && // replacing ... trustedSubjects .get(dn) .contains( // ... weak cert cert.getPublicKey()))) { if (i == 0) { return new X509Certificate[] {chain[0]}; } // Remove and call validator on partial chain [0 .. i-1] X509Certificate[] newChain = new X509Certificate[i]; System.arraycopy(chain, 0, newChain, 0, i); return doValidate(newChain); } prevIssuer = cert.getIssuerX500Principal(); } // apparently issued by trust anchor? X509Certificate last = chain[chain.length - 1]; X500Principal issuer = last.getIssuerX500Principal(); X500Principal subject = last.getSubjectX500Principal(); if (trustedSubjects.containsKey(issuer) && isSignatureValid(trustedSubjects.get(issuer), last)) { return doValidate(chain); } // don't fallback to builder if called from plugin/webstart if (plugin) { // Validate chain even if no trust anchor is found. This // allows plugin/webstart to make sure the chain is // otherwise valid if (chain.length > 1) { X509Certificate[] newChain = new X509Certificate[chain.length - 1]; System.arraycopy(chain, 0, newChain, 0, newChain.length); // temporarily set last cert as sole trust anchor PKIXBuilderParameters params = (PKIXBuilderParameters) parameterTemplate.clone(); try { params.setTrustAnchors( Collections.singleton(new TrustAnchor(chain[chain.length - 1], null))); } catch (InvalidAlgorithmParameterException iape) { // should never occur, but ... throw new CertificateException(iape); } doValidate(newChain, params); } // if the rest of the chain is valid, throw exception // indicating no trust anchor was found throw new ValidatorException(ValidatorException.T_NO_TRUST_ANCHOR); } // otherwise, fall back to builder } return doBuild(chain, otherCerts); }
/** * Search the given Set of TrustAnchor's for one that is the issuer of the given X509 certificate. * * @param cert the X509 certificate * @param params with trust anchors * @return the <code>TrustAnchor</code> object if found or <code>null</code> if not. * @exception CertPathValidatorException if a TrustAnchor was found but the signature verification * on the given certificate has thrown an exception. This Exception can be obtainted with * <code>getCause()</code> method. */ static final TrustAnchor findTrustAnchor( X509Certificate cert, CertPath certPath, int index, PKIXParameters params) throws CertPathValidatorException { // If we have a trust anchor index, use it. if (params instanceof IndexedPKIXParameters) { IndexedPKIXParameters indexed = (IndexedPKIXParameters) params; return indexed.findTrustAnchor(cert, certPath, index); } Iterator iter = params.getTrustAnchors().iterator(); TrustAnchor found = null; PublicKey trustPublicKey = null; Exception invalidKeyEx = null; X509CertSelector certSelectX509 = new X509CertSelector(); try { certSelectX509.setSubject(getEncodedIssuerPrincipal(cert).getEncoded()); } catch (IOException ex) { throw new CertPathValidatorException(ex); } byte[] certBytes = null; try { certBytes = cert.getEncoded(); } catch (Exception e) { // ignore, just continue } while (iter.hasNext() && found == null) { found = (TrustAnchor) iter.next(); X509Certificate foundCert = found.getTrustedCert(); if (foundCert != null) { // If the trust anchor is identical to the certificate we're // done. Just return the anchor. // There is similar code in PKIXCertPathValidatorSpi. try { byte[] foundBytes = foundCert.getEncoded(); if (certBytes != null && Arrays.equals(foundBytes, certBytes)) { return found; } } catch (Exception e) { // ignore, continue and verify the certificate } if (certSelectX509.match(foundCert)) { trustPublicKey = foundCert.getPublicKey(); } else { found = null; } } else if (found.getCAName() != null && found.getCAPublicKey() != null) { try { X500Principal certIssuer = getEncodedIssuerPrincipal(cert); X500Principal caName = new X500Principal(found.getCAName()); if (certIssuer.equals(caName)) { trustPublicKey = found.getCAPublicKey(); } else { found = null; } } catch (IllegalArgumentException ex) { found = null; } } else { found = null; } if (trustPublicKey != null) { try { cert.verify(trustPublicKey); } catch (Exception ex) { invalidKeyEx = ex; found = null; } } } if (found == null && invalidKeyEx != null) { throw new CertPathValidatorException( "TrustAnchor found but certificate validation failed.", invalidKeyEx, certPath, index); } return found; }
public byte[] timeStamp(byte[] data, RevocationData revocationData) throws Exception { // digest the message MessageDigest messageDigest = MessageDigest.getInstance(this.digestAlgo); byte[] digest = messageDigest.digest(data); // generate the TSP request BigInteger nonce = new BigInteger(128, new SecureRandom()); TimeStampRequestGenerator requestGenerator = new TimeStampRequestGenerator(); requestGenerator.setCertReq(true); if (null != this.requestPolicy) { requestGenerator.setReqPolicy(this.requestPolicy); } TimeStampRequest request = requestGenerator.generate(this.digestAlgoOid, digest, nonce); byte[] encodedRequest = request.getEncoded(); // create the HTTP client HttpClient httpClient = new HttpClient(); if (null != this.username) { Credentials credentials = new UsernamePasswordCredentials(this.username, this.password); httpClient.getState().setCredentials(AuthScope.ANY, credentials); } if (null != this.proxyHost) { httpClient.getHostConfiguration().setProxy(this.proxyHost, this.proxyPort); } // create the HTTP POST request PostMethod postMethod = new PostMethod(this.tspServiceUrl); RequestEntity requestEntity = new ByteArrayRequestEntity(encodedRequest, "application/timestamp-query"); postMethod.addRequestHeader("User-Agent", this.userAgent); postMethod.setRequestEntity(requestEntity); // invoke TSP service int statusCode = httpClient.executeMethod(postMethod); if (HttpStatus.SC_OK != statusCode) { LOG.error("Error contacting TSP server " + this.tspServiceUrl); throw new Exception("Error contacting TSP server " + this.tspServiceUrl); } // HTTP input validation Header responseContentTypeHeader = postMethod.getResponseHeader("Content-Type"); if (null == responseContentTypeHeader) { throw new RuntimeException("missing Content-Type header"); } String contentType = responseContentTypeHeader.getValue(); if (!contentType.startsWith("application/timestamp-reply")) { LOG.debug("response content: " + postMethod.getResponseBodyAsString()); throw new RuntimeException("invalid Content-Type: " + contentType); } if (0 == postMethod.getResponseContentLength()) { throw new RuntimeException("Content-Length is zero"); } // TSP response parsing and validation InputStream inputStream = postMethod.getResponseBodyAsStream(); TimeStampResponse timeStampResponse = new TimeStampResponse(inputStream); timeStampResponse.validate(request); if (0 != timeStampResponse.getStatus()) { LOG.debug("status: " + timeStampResponse.getStatus()); LOG.debug("status string: " + timeStampResponse.getStatusString()); PKIFailureInfo failInfo = timeStampResponse.getFailInfo(); if (null != failInfo) { LOG.debug("fail info int value: " + failInfo.intValue()); if (PKIFailureInfo.unacceptedPolicy == failInfo.intValue()) { LOG.debug("unaccepted policy"); } } throw new RuntimeException( "timestamp response status != 0: " + timeStampResponse.getStatus()); } TimeStampToken timeStampToken = timeStampResponse.getTimeStampToken(); SignerId signerId = timeStampToken.getSID(); BigInteger signerCertSerialNumber = signerId.getSerialNumber(); X500Principal signerCertIssuer = signerId.getIssuer(); LOG.debug("signer cert serial number: " + signerCertSerialNumber); LOG.debug("signer cert issuer: " + signerCertIssuer); // TSP signer certificates retrieval CertStore certStore = timeStampToken.getCertificatesAndCRLs("Collection", BouncyCastleProvider.PROVIDER_NAME); Collection<? extends Certificate> certificates = certStore.getCertificates(null); X509Certificate signerCert = null; Map<String, X509Certificate> certificateMap = new HashMap<String, X509Certificate>(); for (Certificate certificate : certificates) { X509Certificate x509Certificate = (X509Certificate) certificate; if (signerCertIssuer.equals(x509Certificate.getIssuerX500Principal()) && signerCertSerialNumber.equals(x509Certificate.getSerialNumber())) { signerCert = x509Certificate; } String ski = Hex.encodeHexString(getSubjectKeyId(x509Certificate)); certificateMap.put(ski, x509Certificate); LOG.debug( "embedded certificate: " + x509Certificate.getSubjectX500Principal() + "; SKI=" + ski); } // TSP signer cert path building if (null == signerCert) { throw new RuntimeException("TSP response token has no signer certificate"); } List<X509Certificate> tspCertificateChain = new LinkedList<X509Certificate>(); X509Certificate certificate = signerCert; do { LOG.debug("adding to certificate chain: " + certificate.getSubjectX500Principal()); tspCertificateChain.add(certificate); if (certificate.getSubjectX500Principal().equals(certificate.getIssuerX500Principal())) { break; } String aki = Hex.encodeHexString(getAuthorityKeyId(certificate)); certificate = certificateMap.get(aki); } while (null != certificate); // verify TSP signer signature timeStampToken.validate(tspCertificateChain.get(0), BouncyCastleProvider.PROVIDER_NAME); // verify TSP signer certificate this.validator.validate(tspCertificateChain, revocationData); LOG.debug("time-stamp token time: " + timeStampToken.getTimeStampInfo().getGenTime()); byte[] timestamp = timeStampToken.getEncoded(); return timestamp; }