Пример #1
0
  /*
   * 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);
  }
Пример #3
0
 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);
       }
     }
   }
 }
Пример #4
0
  /**
   * 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;
  }
Пример #5
0
 /*
  * 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;
  }
Пример #7
0
  /**
   * 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;
  }
Пример #8
0
  /** @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;
  }
Пример #9
0
  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;
  }
Пример #11
0
  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;
  }