/* * 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()); } }
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; }
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); } } } }
/* * 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; }
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); }
/** * 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; }
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"); } }
/** * 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; }
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"); } }
/** * 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; }
/** * 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; }
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); } }
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; }
/** * 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(); }
/** * @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; }
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(); }
/** @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())); }
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; }
/** * 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()); }