예제 #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());
    }
  }
예제 #2
0
  public static String getCertOwner(X509Certificate cert) {
    X500Principal prin = cert.getSubjectX500Principal();

    // get the domain name
    Map<String, String> oidMap = new HashMap<String, String>();
    oidMap.put("1.2.840.113549.1.9.1", "EMAILADDRESS"); // OID for email address
    String prinName = prin.getName(X500Principal.RFC1779, oidMap);

    // see if there is an email address first in the DN
    String searchString = "EMAILADDRESS=";
    int index = prinName.indexOf(searchString);
    if (index == -1) {
      searchString = "CN=";
      // no Email.. check the CN
      index = prinName.indexOf(searchString);
      if (index == -1) return ""; // no CN... nothing else that can be done from here
    }

    // look for a "," to find the end of this attribute
    int endIndex = prinName.indexOf(",", index);
    String address;
    if (endIndex > -1) address = prinName.substring(index + searchString.length(), endIndex);
    else address = prinName.substring(index + searchString.length());

    return address;
  }
예제 #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
 /*
  * 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;
  }
예제 #6
0
  public static String getCertificateFriendlyName(X509Certificate cert) {
    X500Principal principal = cert.getSubjectX500Principal();
    byte[] encodedSubject = principal.getEncoded();
    String friendlyName = null;

    /* Hack so we do not have to ship a whole Spongy/bouncycastle */
    Exception exp = null;
    try {
      Class X509NameClass = Class.forName("com.android.org.bouncycastle.asn1.x509.X509Name");
      Method getInstance = X509NameClass.getMethod("getInstance", Object.class);

      Hashtable defaultSymbols =
          (Hashtable) X509NameClass.getField("DefaultSymbols").get(X509NameClass);

      if (!defaultSymbols.containsKey("1.2.840.113549.1.9.1"))
        defaultSymbols.put("1.2.840.113549.1.9.1", "eMail");

      Object subjectName = getInstance.invoke(X509NameClass, encodedSubject);

      Method toString = X509NameClass.getMethod("toString", boolean.class, Hashtable.class);

      friendlyName = (String) toString.invoke(subjectName, true, defaultSymbols);

    } catch (ClassNotFoundException e) {
      exp = e;
    } catch (NoSuchMethodException e) {
      exp = e;
    } catch (InvocationTargetException e) {
      exp = e;
    } catch (IllegalAccessException e) {
      exp = e;
    } catch (NoSuchFieldException e) {
      exp = e;
    }
    if (exp != null) VpnStatus.logException("Getting X509 Name from certificate", exp);

    /* Fallback if the reflection method did not work */
    if (friendlyName == null) friendlyName = principal.getName();

    // Really evil hack to decode email address
    // See: http://code.google.com/p/android/issues/detail?id=21531

    String[] parts = friendlyName.split(",");
    for (int i = 0; i < parts.length; i++) {
      String part = parts[i];
      if (part.startsWith("1.2.840.113549.1.9.1=#16")) {
        parts[i] = "email=" + ia5decode(part.replace("1.2.840.113549.1.9.1=#16", ""));
      }
    }
    friendlyName = TextUtils.join(",", parts);
    return friendlyName;
  }
 /**
  * Return the subject of a certificate as X500Name, by reparsing if necessary. X500Name should
  * only be used if access to name components is required, in other cases X500Principal is to be
  * prefered.
  *
  * <p>This method is currently used from within JSSE, do not remove.
  */
 public static X500Name getSubjectX500Name(X509Certificate cert)
     throws CertificateParsingException {
   try {
     Principal subjectDN = cert.getSubjectDN();
     if (subjectDN instanceof X500Name) {
       return (X500Name) subjectDN;
     } else {
       X500Principal subjectX500 = cert.getSubjectX500Principal();
       return new X500Name(subjectX500.getEncoded());
     }
   } catch (IOException e) {
     throw (CertificateParsingException) new CertificateParsingException().initCause(e);
   }
 }
 /**
  * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign
  * the certificate.
  */
 public void setIssuerDN(X500Principal issuer) {
   try {
     tbsGen.setIssuer(new X509Principal(issuer.getEncoded()));
   } catch (IOException e) {
     throw new IllegalArgumentException("can't process principal: " + e);
   }
 }
 /**
  * Set the subject distinguished name. The subject describes the entity associated with the public
  * key.
  */
 public void setSubjectDN(X500Principal subject) {
   try {
     tbsGen.setSubject(new X509Principal(subject.getEncoded()));
   } catch (IOException e) {
     throw new IllegalArgumentException("can't process principal: " + e);
   }
 }
  /**
   * 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);
  }
예제 #11
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;
  }
예제 #12
0
 private Set<Rdn> getPrincipalRdns(X500Principal principal) {
   try {
     LdapName certAsLdapName = new LdapName(principal.getName());
     return new HashSet<Rdn>(certAsLdapName.getRdns());
   } catch (InvalidNameException e) {
     throw new SecurityException("Cannot parse '" + principal + "' as LDAP name");
   }
 }
예제 #13
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;
  }
예제 #14
0
 private static X509Name convertName(X500Principal var0) {
   try {
     byte[] var1 = var0.getEncoded();
     X509Principal var2 = new X509Principal(var1);
     return var2;
   } catch (IOException var4) {
     throw new IllegalArgumentException("can\'t convert name");
   }
 }
예제 #15
0
 /**
  * Converts the given X.500 principal to a list of type/value attributes.
  *
  * @param principal Principal to convert.
  * @return List of type/value attributes.
  */
 public static Attributes readX500Principal(final X500Principal principal) {
   final X500Name name = X500Name.getInstance(principal.getEncoded());
   final Attributes attributes = new Attributes();
   for (RDN rdn : name.getRDNs()) {
     for (AttributeTypeAndValue tv : rdn.getTypesAndValues()) {
       attributes.add(tv.getType().getId(), tv.getValue().toString());
     }
   }
   return attributes;
 }
예제 #16
0
 /**
  * Converts the given X.500 principal to a list of relative distinguished names that contains the
  * attributes comprising the DN.
  *
  * @param principal Principal to convert.
  * @return X500 principal as an RDN sequence.
  */
 public static RDNSequence readX500Principal(final X500Principal principal) {
   final X500Name name = X500Name.getInstance(principal.getEncoded());
   final RDNSequence sequence = new RDNSequence();
   for (org.bouncycastle.asn1.x500.RDN rdn : name.getRDNs()) {
     final Attributes attributes = new Attributes();
     for (AttributeTypeAndValue tv : rdn.getTypesAndValues()) {
       attributes.add(tv.getType().getId(), tv.getValue().toString());
     }
     sequence.add(new RDN(attributes));
   }
   return sequence;
 }
예제 #17
0
 private static int X509_NAME_hash(X500Principal principal, String algorithm) {
   try {
     byte[] digest = MessageDigest.getInstance(algorithm).digest(principal.getEncoded());
     int offset = 0;
     return (((digest[offset++] & 0xff) << 0)
         | ((digest[offset++] & 0xff) << 8)
         | ((digest[offset++] & 0xff) << 16)
         | ((digest[offset] & 0xff) << 24));
   } catch (NoSuchAlgorithmException e) {
     throw new AssertionError(e);
   }
 }
예제 #18
0
 private VomsExtensions(
     String proxySubject,
     String proxySubjectIssuer,
     String vo,
     String vomsSubject,
     X500Principal x500,
     String fqan,
     boolean primary) {
   _x509Subject = proxySubject;
   _x509SubjectIssuer = proxySubjectIssuer;
   _vo = vo;
   _vomsSubject = vomsSubject;
   if (x500 != null) {
     _vomsSubjectIssuer = X509Utils.toGlobusDN(x500.toString(), true);
   }
   _fqan = fqan;
   _primary = primary;
 }
예제 #19
0
  /**
   * Converts DN of the form "CN=A, OU=B, O=C" into Globus format "/O=C/OU=B/CN=A" <br>
   * This function might return incorrect Globus-formatted ID when one of the RDNs in the DN
   * contains commas.
   *
   * @return the converted DN in Globus format.
   */
  public static String toGlobusID(X500Principal principal) {

    if (principal == null) {
      return null;
    }

    String dn = principal.getName();

    StringTokenizer tokens = new StringTokenizer(dn, ",");
    StringBuffer buf = new StringBuffer();
    String token;

    while (tokens.hasMoreTokens()) {
      token = tokens.nextToken().trim();
      buf.insert(0, token);
      buf.insert(0, "/");
    }
    return buf.toString();
  }
예제 #20
0
  /**
   * @param aliasName
   * @param publicKey
   * @param privateKey
   * @return the DER encoded Certificate Signing Request.
   * @throws IOException
   * @throws InvalidKeyException
   * @throws SignatureException
   */
  private byte[] getCSR(X500Principal aliasName, PublicKey publicKey, PrivateKey privateKey)
      throws IOException, InvalidKeyException, SignatureException {
    DERValue derVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
    DERValue derSubject = new DERReader(aliasName.getEncoded()).read();
    DERValue derSubjectPKInfo = new DERReader(publicKey.getEncoded()).read();
    byte[] b = nullAttributes ? new byte[] {0x05, 0x00} : new byte[0];
    DERValue derAttributes = new DERValue(DER.CONSTRUCTED | DER.CONTEXT | 0, b.length, b, null);
    ArrayList certRequestInfo = new ArrayList(4);
    certRequestInfo.add(derVersion);
    certRequestInfo.add(derSubject);
    certRequestInfo.add(derSubjectPKInfo);
    certRequestInfo.add(derAttributes);
    DERValue derCertRequestInfo = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, certRequestInfo);

    OID sigAlgorithmID = getSignatureAlgorithmOID();
    DERValue derSigAlgorithmID = new DERValue(DER.OBJECT_IDENTIFIER, sigAlgorithmID);
    ArrayList sigAlgorithm = new ArrayList(2);
    sigAlgorithm.add(derSigAlgorithmID);
    if (!sigAlgorithmID.equals(Command.SHA1_WITH_DSA)) // it's an RSA-based
    sigAlgorithm.add(new DERValue(DER.NULL, null));

    sigAlgorithm.trimToSize();
    DERValue derSignatureAlgorithm = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, sigAlgorithm);

    signatureAlgorithm.initSign(privateKey);
    signatureAlgorithm.update(derCertRequestInfo.getEncoded());
    byte[] sigBytes = signatureAlgorithm.sign();
    DERValue derSignature = new DERValue(DER.BIT_STRING, new BitString(sigBytes));

    ArrayList csr = new ArrayList(3);
    csr.add(derCertRequestInfo);
    csr.add(derSignatureAlgorithm);
    csr.add(derSignature);
    DERValue derCSR = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, csr);

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    DERWriter.write(baos, derCSR);
    byte[] result = baos.toByteArray();

    return result;
  }
예제 #21
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);
  }
 public String encode() {
   return value.getName();
 }
 /**
  * Returns the hashcode value used to index and compare this object with others of the same type.
  * Typically this is the hashcode of the backing data object.
  *
  * @return the object's hashcode value
  */
 public int hashCode() {
   return value.hashCode();
 }
예제 #24
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;
  }
  /**
   * Appends an HTML representation of the given X509Certificate.
   *
   * @param sb StringBuilder to append to
   * @param certificate to print
   */
  private void renderX509(StringBuilder sb, X509Certificate certificate) {
    X500Principal issuer = certificate.getIssuerX500Principal();
    X500Principal subject = certificate.getSubjectX500Principal();

    sb.append("<table cellspacing='1' cellpadding='1'>\n");

    // subject
    addTitle(sb, R.getI18NString("service.gui.CERT_INFO_ISSUED_TO"));
    try {
      for (Rdn name : new LdapName(subject.getName()).getRdns()) {
        String nameType = name.getType();
        String lblKey = "service.gui.CERT_INFO_" + nameType;
        String lbl = R.getI18NString(lblKey);

        if ((lbl == null) || ("!" + lblKey + "!").equals(lbl)) lbl = nameType;

        final String value;
        Object nameValue = name.getValue();

        if (nameValue instanceof byte[]) {
          byte[] nameValueAsByteArray = (byte[]) nameValue;

          value = getHex(nameValueAsByteArray) + " (" + new String(nameValueAsByteArray) + ")";
        } else value = nameValue.toString();

        addField(sb, lbl, value);
      }
    } catch (InvalidNameException ine) {
      addField(sb, R.getI18NString("service.gui.CERT_INFO_CN"), subject.getName());
    }

    // issuer
    addTitle(sb, R.getI18NString("service.gui.CERT_INFO_ISSUED_BY"));
    try {
      for (Rdn name : new LdapName(issuer.getName()).getRdns()) {
        String nameType = name.getType();
        String lblKey = "service.gui.CERT_INFO_" + nameType;
        String lbl = R.getI18NString(lblKey);

        if ((lbl == null) || ("!" + lblKey + "!").equals(lbl)) lbl = nameType;

        final String value;
        Object nameValue = name.getValue();

        if (nameValue instanceof byte[]) {
          byte[] nameValueAsByteArray = (byte[]) nameValue;

          value = getHex(nameValueAsByteArray) + " (" + new String(nameValueAsByteArray) + ")";
        } else value = nameValue.toString();

        addField(sb, lbl, value);
      }
    } catch (InvalidNameException ine) {
      addField(sb, R.getI18NString("service.gui.CERT_INFO_CN"), issuer.getName());
    }

    // validity
    addTitle(sb, R.getI18NString("service.gui.CERT_INFO_VALIDITY"));
    addField(
        sb,
        R.getI18NString("service.gui.CERT_INFO_ISSUED_ON"),
        certificate.getNotBefore().toString());
    addField(
        sb,
        R.getI18NString("service.gui.CERT_INFO_EXPIRES_ON"),
        certificate.getNotAfter().toString());

    addTitle(sb, R.getI18NString("service.gui.CERT_INFO_FINGERPRINTS"));
    try {
      String sha1String = getThumbprint(certificate, "SHA1");
      String md5String = getThumbprint(certificate, "MD5");

      addField(sb, "SHA1:", sha1String);
      addField(sb, "MD5:", md5String);
    } catch (CertificateException e) {
      // do nothing as we cannot show this value
    }

    addTitle(sb, R.getI18NString("service.gui.CERT_INFO_CERT_DETAILS"));

    addField(
        sb,
        R.getI18NString("service.gui.CERT_INFO_SER_NUM"),
        certificate.getSerialNumber().toString());

    addField(
        sb, R.getI18NString("service.gui.CERT_INFO_VER"), String.valueOf(certificate.getVersion()));

    addField(
        sb,
        R.getI18NString("service.gui.CERT_INFO_SIGN_ALG"),
        String.valueOf(certificate.getSigAlgName()));

    addTitle(sb, R.getI18NString("service.gui.CERT_INFO_PUB_KEY_INFO"));

    addField(
        sb,
        R.getI18NString("service.gui.CERT_INFO_ALG"),
        certificate.getPublicKey().getAlgorithm());

    if (certificate.getPublicKey().getAlgorithm().equals("RSA")) {
      RSAPublicKey key = (RSAPublicKey) certificate.getPublicKey();

      addField(
          sb,
          R.getI18NString("service.gui.CERT_INFO_PUB_KEY"),
          R.getI18NString(
              "service.gui.CERT_INFO_KEY_BYTES_PRINT",
              new String[] {
                String.valueOf(key.getModulus().toByteArray().length - 1),
                key.getModulus().toString(16)
              }));

      addField(
          sb, R.getI18NString("service.gui.CERT_INFO_EXP"), key.getPublicExponent().toString());

      addField(
          sb,
          R.getI18NString("service.gui.CERT_INFO_KEY_SIZE"),
          R.getI18NString(
              "service.gui.CERT_INFO_KEY_BITS_PRINT",
              new String[] {String.valueOf(key.getModulus().bitLength())}));
    } else if (certificate.getPublicKey().getAlgorithm().equals("DSA")) {
      DSAPublicKey key = (DSAPublicKey) certificate.getPublicKey();

      addField(sb, "Y:", key.getY().toString(16));
    }

    addField(
        sb,
        R.getI18NString("service.gui.CERT_INFO_SIGN"),
        R.getI18NString(
            "service.gui.CERT_INFO_KEY_BYTES_PRINT",
            new String[] {
              String.valueOf(certificate.getSignature().length), getHex(certificate.getSignature())
            }));

    sb.append("</table>\n");
  }
 public AttributeCertificateIssuer(X500Principal principal) throws IOException {
   this(new X509Principal(principal.getEncoded()));
 }
예제 #27
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;
  }
예제 #28
0
  /**
   * Uses the provided PKI method to find the corresponding public key and verify the provided
   * signature. Returns null if no PKI method was specified in the {@link Protos.PaymentRequest}.
   */
  public @Nullable PkiVerificationData verifyPki() throws PaymentRequestException {
    try {
      if (pkiVerificationData != null) return pkiVerificationData;
      if (paymentRequest.getPkiType().equals("none"))
        // Nothing to verify. Everything is fine. Move along.
        return null;

      String algorithm;
      if (paymentRequest.getPkiType().equals("x509+sha256")) algorithm = "SHA256withRSA";
      else if (paymentRequest.getPkiType().equals("x509+sha1")) algorithm = "SHA1withRSA";
      else
        throw new PaymentRequestException.InvalidPkiType(
            "Unsupported PKI type: " + paymentRequest.getPkiType());

      Protos.X509Certificates protoCerts =
          Protos.X509Certificates.parseFrom(paymentRequest.getPkiData());
      if (protoCerts.getCertificateCount() == 0)
        throw new PaymentRequestException.InvalidPkiData(
            "No certificates provided in message: server config error");

      // Parse the certs and turn into a certificate chain object. Cert factories can parse both DER
      // and base64.
      // The ordering of certificates is defined by the payment protocol spec to be the same as what
      // the Java
      // crypto API requires - convenient!
      CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
      List<X509Certificate> certs = Lists.newArrayList();
      for (ByteString bytes : protoCerts.getCertificateList())
        certs.add((X509Certificate) certificateFactory.generateCertificate(bytes.newInput()));
      CertPath path = certificateFactory.generateCertPath(certs);

      // Retrieves the most-trusted CAs from keystore.
      PKIXParameters params = new PKIXParameters(createKeyStore(trustStorePath));
      // Revocation not supported in the current version.
      params.setRevocationEnabled(false);

      // Now verify the certificate chain is correct and trusted. This let's us get an identity
      // linked pubkey.
      CertPathValidator validator = CertPathValidator.getInstance("PKIX");
      PKIXCertPathValidatorResult result =
          (PKIXCertPathValidatorResult) validator.validate(path, params);
      PublicKey publicKey = result.getPublicKey();
      // OK, we got an identity, now check it was used to sign this message.
      Signature signature = Signature.getInstance(algorithm);
      // Note that we don't use signature.initVerify(certs.get(0)) here despite it being the most
      // obvious
      // way to set it up, because we don't care about the constraints specified on the
      // certificates: any
      // cert that links a key to a domain name or other identity will do for us.
      signature.initVerify(publicKey);
      Protos.PaymentRequest.Builder reqToCheck = paymentRequest.toBuilder();
      reqToCheck.setSignature(ByteString.EMPTY);
      signature.update(reqToCheck.build().toByteArray());
      if (!signature.verify(paymentRequest.getSignature().toByteArray()))
        throw new PaymentRequestException.PkiVerificationException(
            "Invalid signature, this payment request is not valid.");

      // Signature verifies, get the names from the identity we just verified for presentation to
      // the user.
      X500Principal principal = certs.get(0).getSubjectX500Principal();
      // At this point the Java crypto API falls flat on its face and dies - there's no clean way to
      // get the
      // different parts of the certificate name except for parsing the string. That's hard because
      // of various
      // custom escaping rules and the usual crap. So, use Bouncy Castle to re-parse the string into
      // binary form
      // again and then look for the names we want. Fail!
      org.spongycastle.asn1.x500.X500Name name = new X500Name(principal.getName());
      String entityName = null, orgName = null;
      for (RDN rdn : name.getRDNs()) {
        AttributeTypeAndValue pair = rdn.getFirst();
        if (pair.getType().equals(RFC4519Style.cn))
          entityName = ((ASN1String) pair.getValue()).getString();
        else if (pair.getType().equals(RFC4519Style.o))
          orgName = ((ASN1String) pair.getValue()).getString();
      }
      if (entityName == null && orgName == null)
        throw new PaymentRequestException.PkiVerificationException(
            "Invalid certificate, no CN or O fields");
      // Everything is peachy. Return some useful data to the caller.
      PkiVerificationData data =
          new PkiVerificationData(entityName, orgName, publicKey, result.getTrustAnchor());
      // Cache the result so we don't have to re-verify if this method is called again.
      pkiVerificationData = data;
      return data;
    } catch (InvalidProtocolBufferException e) {
      // Data structures are malformed.
      throw new PaymentRequestException.InvalidPkiData(e);
    } catch (CertificateException e) {
      // The X.509 certificate data didn't parse correctly.
      throw new PaymentRequestException.PkiVerificationException(e);
    } catch (NoSuchAlgorithmException e) {
      // Should never happen so don't make users have to think about it. PKIX is always present.
      throw new RuntimeException(e);
    } catch (InvalidAlgorithmParameterException e) {
      throw new RuntimeException(e);
    } catch (CertPathValidatorException e) {
      // The certificate chain isn't known or trusted, probably, the server is using an SSL root we
      // don't
      // know about and the user needs to upgrade to a new version of the software (or import a root
      // cert).
      throw new PaymentRequestException.PkiVerificationException(e);
    } catch (InvalidKeyException e) {
      // Shouldn't happen if the certs verified correctly.
      throw new PaymentRequestException.PkiVerificationException(e);
    } catch (SignatureException e) {
      // Something went wrong during hashing (yes, despite the name, this does not mean the sig was
      // invalid).
      throw new PaymentRequestException.PkiVerificationException(e);
    } catch (IOException e) {
      throw new PaymentRequestException.PkiVerificationException(e);
    } catch (KeyStoreException e) {
      throw new RuntimeException(e);
    }
  }
  /**
   * 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 SigningPolicy getSigningPolicy(X500Principal caPrincipal)
     throws SigningPolicyStoreException {
   return store.get(caPrincipal.getName());
 }