aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/mail/src/main/java/org/spongycastle/mail/smime/validator/SignedMailValidator.java
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/spongycastle/mail/src/main/java/org/spongycastle/mail/smime/validator/SignedMailValidator.java')
-rw-r--r--libraries/spongycastle/mail/src/main/java/org/spongycastle/mail/smime/validator/SignedMailValidator.java960
1 files changed, 0 insertions, 960 deletions
diff --git a/libraries/spongycastle/mail/src/main/java/org/spongycastle/mail/smime/validator/SignedMailValidator.java b/libraries/spongycastle/mail/src/main/java/org/spongycastle/mail/smime/validator/SignedMailValidator.java
deleted file mode 100644
index 21132852c..000000000
--- a/libraries/spongycastle/mail/src/main/java/org/spongycastle/mail/smime/validator/SignedMailValidator.java
+++ /dev/null
@@ -1,960 +0,0 @@
-package org.bouncycastle.mail.smime.validator;
-
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-import java.security.PublicKey;
-import java.security.cert.CertPath;
-import java.security.cert.CertStore;
-import java.security.cert.CertStoreException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.PKIXParameters;
-import java.security.cert.TrustAnchor;
-import java.security.cert.X509CertSelector;
-import java.security.cert.X509Certificate;
-import java.security.interfaces.DSAPublicKey;
-import java.security.interfaces.RSAPublicKey;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Vector;
-
-import javax.mail.Address;
-import javax.mail.MessagingException;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeMessage;
-import javax.mail.internet.MimeMultipart;
-
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.cms.Attribute;
-import org.bouncycastle.asn1.cms.AttributeTable;
-import org.bouncycastle.asn1.cms.CMSAttributes;
-import org.bouncycastle.asn1.cms.Time;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
-import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
-import org.bouncycastle.asn1.x509.KeyPurposeId;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.cert.jcajce.JcaCertStoreBuilder;
-import org.bouncycastle.cms.SignerInformation;
-import org.bouncycastle.cms.SignerInformationStore;
-import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
-import org.bouncycastle.cms.jcajce.JcaX509CertSelectorConverter;
-import org.bouncycastle.i18n.ErrorBundle;
-import org.bouncycastle.i18n.filter.TrustedInput;
-import org.bouncycastle.i18n.filter.UntrustedInput;
-import org.bouncycastle.jce.PrincipalUtil;
-import org.bouncycastle.jce.X509Principal;
-import org.bouncycastle.mail.smime.SMIMESigned;
-import org.bouncycastle.util.Integers;
-import org.bouncycastle.x509.CertPathReviewerException;
-import org.bouncycastle.x509.PKIXCertPathReviewer;
-
-public class SignedMailValidator
-{
- private static final String RESOURCE_NAME = "org.bouncycastle.mail.smime.validator.SignedMailValidatorMessages";
-
- private static final Class DEFAULT_CERT_PATH_REVIEWER = PKIXCertPathReviewer.class;
-
- private static final String EXT_KEY_USAGE = X509Extensions.ExtendedKeyUsage
- .getId();
-
- private static final String SUBJECT_ALTERNATIVE_NAME = X509Extensions.SubjectAlternativeName
- .getId();
-
- private static final int shortKeyLength = 512;
-
- // (365.25*30)*24*3600*1000
- private static final long THIRTY_YEARS_IN_MILLI_SEC = 21915l*12l*3600l*1000l;
-
- private static final JcaX509CertSelectorConverter selectorConverter = new JcaX509CertSelectorConverter();
-
- private CertStore certs;
-
- private SignerInformationStore signers;
-
- private Map results;
-
- private String[] fromAddresses;
-
- private Class certPathReviewerClass;
-
- /**
- * Validates the signed {@link MimeMessage} message. The
- * {@link PKIXParameters} from param are used for the certificate path
- * validation. The actual PKIXParameters used for the certificate path
- * validation is a copy of param with the followin changes: <br> - The
- * validation date is changed to the signature time <br> - A CertStore with
- * certificates and crls from the mail message is added to the CertStores.<br>
- * <br>
- * In <code>param</code> it's also possible to add additional CertStores
- * with intermediate Certificates and/or CRLs which then are also used for
- * the validation.
- *
- * @param message
- * the signed MimeMessage
- * @param param
- * the parameters for the certificate path validation
- * @throws SignedMailValidatorException
- * if the message is no signed message or if an exception occurs
- * reading the message
- */
- public SignedMailValidator(MimeMessage message, PKIXParameters param)
- throws SignedMailValidatorException
- {
- this(message, param, DEFAULT_CERT_PATH_REVIEWER);
- }
-
- /**
- * Validates the signed {@link MimeMessage} message. The
- * {@link PKIXParameters} from param are used for the certificate path
- * validation. The actual PKIXParameters used for the certificate path
- * validation is a copy of param with the followin changes: <br> - The
- * validation date is changed to the signature time <br> - A CertStore with
- * certificates and crls from the mail message is added to the CertStores.<br>
- * <br>
- * In <code>param</code> it's also possible to add additional CertStores
- * with intermediate Certificates and/or CRLs which then are also used for
- * the validation.
- *
- * @param message
- * the signed MimeMessage
- * @param param
- * the parameters for the certificate path validation
- * @param certPathReviewerClass
- * a subclass of {@link PKIXCertPathReviewer}. The SignedMailValidator
- * uses objects of this type for the cert path vailidation. The class must
- * have an empty constructor.
- * @throws SignedMailValidatorException
- * if the message is no signed message or if an exception occurs
- * reading the message
- * @throws IllegalArgumentException if the certPathReviewerClass is not a
- * subclass of {@link PKIXCertPathReviewer} or objects of
- * certPathReviewerClass can not be instantiated
- */
- public SignedMailValidator(MimeMessage message, PKIXParameters param, Class certPathReviewerClass)
- throws SignedMailValidatorException
- {
- this.certPathReviewerClass = certPathReviewerClass;
- boolean isSubclass = DEFAULT_CERT_PATH_REVIEWER.isAssignableFrom(certPathReviewerClass);
- if(!isSubclass)
- {
- throw new IllegalArgumentException("certPathReviewerClass is not a subclass of " + DEFAULT_CERT_PATH_REVIEWER.getName());
- }
-
- SMIMESigned s;
-
- try
- {
- // check if message is multipart signed
- if (message.isMimeType("multipart/signed"))
- {
- MimeMultipart mimemp = (MimeMultipart) message.getContent();
- s = new SMIMESigned(mimemp);
- }
- else if (message.isMimeType("application/pkcs7-mime")
- || message.isMimeType("application/x-pkcs7-mime"))
- {
- s = new SMIMESigned(message);
- }
- else
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.noSignedMessage");
- throw new SignedMailValidatorException(msg);
- }
-
- // save certstore and signerInformationStore
- certs = new JcaCertStoreBuilder().addCertificates(s.getCertificates()).addCRLs(s.getCRLs()).setProvider("BC").build();
- signers = s.getSignerInfos();
-
- // save "from" addresses from message
- Address[] froms = message.getFrom();
- InternetAddress sender = null;
- try
- {
- if(message.getHeader("Sender") != null)
- {
- sender = new InternetAddress(message.getHeader("Sender")[0]);
- }
- }
- catch (MessagingException ex)
- {
- //ignore garbage in Sender: header
- }
- fromAddresses = new String[froms.length + (sender!=null?1:0)];
- for (int i = 0; i < froms.length; i++)
- {
- InternetAddress inetAddr = (InternetAddress) froms[i];
- fromAddresses[i] = inetAddr.getAddress();
- }
- if(sender!=null)
- {
- fromAddresses[froms.length] = sender.getAddress();
- }
-
- // initialize results
- results = new HashMap();
- }
- catch (Exception e)
- {
- if (e instanceof SignedMailValidatorException)
- {
- throw (SignedMailValidatorException) e;
- }
- // exception reading message
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.exceptionReadingMessage",
- new Object[] { e.getMessage(), e , e.getClass().getName()});
- throw new SignedMailValidatorException(msg, e);
- }
-
- // validate signatues
- validateSignatures(param);
- }
-
- protected void validateSignatures(PKIXParameters pkixParam)
- {
- PKIXParameters usedParameters = (PKIXParameters) pkixParam.clone();
-
- // add crls and certs from mail
- usedParameters.addCertStore(certs);
-
- Collection c = signers.getSigners();
- Iterator it = c.iterator();
-
- // check each signer
- while (it.hasNext())
- {
- List errors = new ArrayList();
- List notifications = new ArrayList();
-
- SignerInformation signer = (SignerInformation) it.next();
- // signer certificate
- X509Certificate cert = null;
-
- try
- {
- Collection certCollection = findCerts(usedParameters
- .getCertStores(), selectorConverter.getCertSelector(signer.getSID()));
-
- Iterator certIt = certCollection.iterator();
- if (certIt.hasNext())
- {
- cert = (X509Certificate) certIt.next();
- }
- }
- catch (CertStoreException cse)
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.exceptionRetrievingSignerCert",
- new Object[] { cse.getMessage(), cse , cse.getClass().getName()});
- errors.add(msg);
- }
-
- if (cert != null)
- {
- // check signature
- boolean validSignature = false;
- try
- {
- validSignature = signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert.getPublicKey()));
- if (!validSignature)
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.signatureNotVerified");
- errors.add(msg);
- }
- }
- catch (Exception e)
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.exceptionVerifyingSignature",
- new Object[] { e.getMessage(), e, e.getClass().getName() });
- errors.add(msg);
- }
-
- // check signer certificate (mail address, key usage, etc)
- checkSignerCert(cert, errors, notifications);
-
- // notify if a signed receip request is in the message
- AttributeTable atab = signer.getSignedAttributes();
- if (atab != null)
- {
- Attribute attr = atab.get(PKCSObjectIdentifiers.id_aa_receiptRequest);
- if (attr != null)
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.signedReceiptRequest");
- notifications.add(msg);
- }
- }
-
- // check certificate path
-
- // get signing time if possible, otherwise use current time as
- // signing time
- Date signTime = getSignatureTime(signer);
- if (signTime == null) // no signing time was found
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.noSigningTime");
- errors.add(msg);
- signTime = new Date();
- }
- else
- {
- // check if certificate was valid at signing time
- try
- {
- cert.checkValidity(signTime);
- }
- catch (CertificateExpiredException e)
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.certExpired",
- new Object[] { new TrustedInput(signTime), new TrustedInput(cert.getNotAfter()) });
- errors.add(msg);
- }
- catch (CertificateNotYetValidException e)
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.certNotYetValid",
- new Object[] { new TrustedInput(signTime), new TrustedInput(cert.getNotBefore()) });
- errors.add(msg);
- }
- }
- usedParameters.setDate(signTime);
-
- try
- {
- // construct cert chain
- CertPath certPath;
- List userProvidedList;
-
- List userCertStores = new ArrayList();
- userCertStores.add(certs);
- Object[] cpres = createCertPath(cert, usedParameters.getTrustAnchors(), pkixParam.getCertStores(), userCertStores);
- certPath = (CertPath) cpres[0];
- userProvidedList = (List) cpres[1];
-
- // validate cert chain
- PKIXCertPathReviewer review;
- try
- {
- review = (PKIXCertPathReviewer)certPathReviewerClass.newInstance();
- }
- catch (IllegalAccessException e)
- {
- throw new IllegalArgumentException("Cannot instantiate object of type " +
- certPathReviewerClass.getName() + ": " + e.getMessage());
- }
- catch (InstantiationException e)
- {
- throw new IllegalArgumentException("Cannot instantiate object of type " +
- certPathReviewerClass.getName() + ": " + e.getMessage());
- }
- review.init(certPath, usedParameters);
- if (!review.isValidCertPath())
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.certPathInvalid");
- errors.add(msg);
- }
- results.put(signer, new ValidationResult(review,
- validSignature, errors, notifications, userProvidedList));
- }
- catch (GeneralSecurityException gse)
- {
- // cannot create cert path
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.exceptionCreateCertPath",
- new Object[] { gse.getMessage(), gse, gse.getClass().getName() });
- errors.add(msg);
- results.put(signer, new ValidationResult(null,
- validSignature, errors, notifications, null));
- }
- catch (CertPathReviewerException cpre)
- {
- // cannot initialize certpathreviewer - wrong parameters
- errors.add(cpre.getErrorMessage());
- results.put(signer, new ValidationResult(null,
- validSignature, errors, notifications, null));
- }
- }
- else
- // no signer certificate found
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.noSignerCert");
- errors.add(msg);
- results.put(signer, new ValidationResult(null, false, errors,
- notifications, null));
- }
- }
- }
-
- public static Set getEmailAddresses(X509Certificate cert) throws IOException, CertificateEncodingException
- {
- Set addresses = new HashSet();
-
- X509Principal name = PrincipalUtil.getSubjectX509Principal(cert);
- Vector oids = name.getOIDs();
- Vector names = name.getValues();
- for (int i = 0; i < oids.size(); i++)
- {
- if (oids.get(i).equals(X509Principal.EmailAddress))
- {
- String email = ((String) names.get(i)).toLowerCase();
- addresses.add(email);
- break;
- }
- }
-
- byte[] ext = cert.getExtensionValue(SUBJECT_ALTERNATIVE_NAME);
- if (ext != null)
- {
- ASN1Sequence altNames = ASN1Sequence.getInstance(getObject(ext));
- for (int j = 0; j < altNames.size(); j++)
- {
- ASN1TaggedObject o = (ASN1TaggedObject) altNames
- .getObjectAt(j);
-
- if (o.getTagNo() == 1)
- {
- String email = DERIA5String.getInstance(o, false)
- .getString().toLowerCase();
- addresses.add(email);
- }
- }
- }
-
- return addresses;
- }
-
- private static ASN1Primitive getObject(byte[] ext) throws IOException
- {
- ASN1InputStream aIn = new ASN1InputStream(ext);
- ASN1OctetString octs = (ASN1OctetString) aIn.readObject();
-
- aIn = new ASN1InputStream(octs.getOctets());
- return aIn.readObject();
- }
-
- protected void checkSignerCert(X509Certificate cert, List errors,
- List notifications)
- {
- // get key length
- PublicKey key = cert.getPublicKey();
- int keyLenght = -1;
- if (key instanceof RSAPublicKey)
- {
- keyLenght = ((RSAPublicKey) key).getModulus().bitLength();
- }
- else if (key instanceof DSAPublicKey)
- {
- keyLenght = ((DSAPublicKey) key).getParams().getP().bitLength();
- }
- if (keyLenght != -1 && keyLenght <= shortKeyLength)
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.shortSigningKey",
- new Object[]{Integers.valueOf(keyLenght)});
- notifications.add(msg);
- }
-
- // warn if certificate has very long validity period
- long validityPeriod = cert.getNotAfter().getTime() - cert.getNotBefore().getTime();
- if (validityPeriod > THIRTY_YEARS_IN_MILLI_SEC)
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.longValidity",
- new Object[] {new TrustedInput(cert.getNotBefore()), new TrustedInput(cert.getNotAfter())});
- notifications.add(msg);
- }
-
- // check key usage if digitalSignature or nonRepudiation is set
- boolean[] keyUsage = cert.getKeyUsage();
- if (keyUsage != null && !keyUsage[0] && !keyUsage[1])
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.signingNotPermitted");
- errors.add(msg);
- }
-
- // check extended key usage
- try
- {
- byte[] ext = cert.getExtensionValue(EXT_KEY_USAGE);
- if (ext != null)
- {
- ExtendedKeyUsage extKeyUsage = ExtendedKeyUsage
- .getInstance(getObject(ext));
- if (!extKeyUsage
- .hasKeyPurposeId(KeyPurposeId.anyExtendedKeyUsage)
- && !extKeyUsage
- .hasKeyPurposeId(KeyPurposeId.id_kp_emailProtection))
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.extKeyUsageNotPermitted");
- errors.add(msg);
- }
- }
- }
- catch (Exception e)
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.extKeyUsageError", new Object[] {
- e.getMessage(), e, e.getClass().getName() });
- errors.add(msg);
- }
-
- // cert has an email address
- try
- {
- Set certEmails = getEmailAddresses(cert);
- if (certEmails.isEmpty())
- {
- // error no email address in signing certificate
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.noEmailInCert");
- errors.add(msg);
- }
- else
- {
- // check if email in cert is equal to the from address in the
- // message
- boolean equalsFrom = false;
- for (int i = 0; i < fromAddresses.length; i++)
- {
- if (certEmails.contains(fromAddresses[i].toLowerCase()))
- {
- equalsFrom = true;
- break;
- }
- }
- if (!equalsFrom)
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.emailFromCertMismatch",
- new Object[] {
- new UntrustedInput(
- addressesToString(fromAddresses)),
- new UntrustedInput(certEmails) });
- errors.add(msg);
- }
- }
- }
- catch (Exception e)
- {
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.certGetEmailError", new Object[] {
- e.getMessage(), e, e.getClass().getName() });
- errors.add(msg);
- }
- }
-
- static String addressesToString(Object[] a)
- {
- if (a == null)
- {
- return "null";
- }
-
- StringBuffer b = new StringBuffer();
- b.append('[');
-
- for (int i = 0; i != a.length; i++)
- {
- if (i > 0)
- {
- b.append(", ");
- }
- b.append(String.valueOf(a[i]));
- }
-
- return b.append(']').toString();
- }
-
- public static Date getSignatureTime(SignerInformation signer)
- {
- AttributeTable atab = signer.getSignedAttributes();
- Date result = null;
- if (atab != null)
- {
- Attribute attr = atab.get(CMSAttributes.signingTime);
- if (attr != null)
- {
- Time t = Time.getInstance(attr.getAttrValues().getObjectAt(0)
- .toASN1Primitive());
- result = t.getDate();
- }
- }
- return result;
- }
-
- private static List findCerts(List certStores, X509CertSelector selector)
- throws CertStoreException
- {
- List result = new ArrayList();
- Iterator it = certStores.iterator();
- while (it.hasNext())
- {
- CertStore store = (CertStore) it.next();
- Collection coll = store.getCertificates(selector);
- result.addAll(coll);
- }
- return result;
- }
-
- private static X509Certificate findNextCert(List certStores, X509CertSelector selector, Set certSet)
- throws CertStoreException
- {
- Iterator certIt = findCerts(certStores, selector).iterator();
-
- boolean certFound = false;
- X509Certificate nextCert = null;
- while (certIt.hasNext())
- {
- nextCert = (X509Certificate) certIt.next();
- if (!certSet.contains(nextCert))
- {
- certFound = true;
- break;
- }
- }
-
- return certFound ? nextCert : null;
- }
-
- /**
- *
- * @param signerCert the end of the path
- * @param trustanchors trust anchors for the path
- * @param certStores
- * @return the resulting certificate path.
- * @throws GeneralSecurityException
- */
- public static CertPath createCertPath(X509Certificate signerCert,
- Set trustanchors, List certStores) throws GeneralSecurityException
- {
- Object[] results = createCertPath(signerCert, trustanchors, certStores, null);
- return (CertPath) results[0];
- }
-
- /**
- * Returns an Object array containing a CertPath and a List of Booleans. The list contains the value <code>true</code>
- * if the corresponding certificate in the CertPath was taken from the user provided CertStores.
- * @param signerCert the end of the path
- * @param trustanchors trust anchors for the path
- * @param systemCertStores list of {@link CertStore} provided by the system
- * @param userCertStores list of {@link CertStore} provided by the user
- * @return a CertPath and a List of booleans.
- * @throws GeneralSecurityException
- */
- public static Object[] createCertPath(X509Certificate signerCert,
- Set trustanchors, List systemCertStores, List userCertStores) throws GeneralSecurityException
- {
- Set certSet = new LinkedHashSet();
- List userProvidedList = new ArrayList();
-
- // add signer certificate
-
- X509Certificate cert = signerCert;
- certSet.add(cert);
- userProvidedList.add(new Boolean(true));
-
- boolean trustAnchorFound = false;
-
- X509Certificate taCert = null;
-
- // add other certs to the cert path
- while (cert != null && !trustAnchorFound)
- {
- // check if cert Issuer is Trustanchor
- Iterator trustIt = trustanchors.iterator();
- while (trustIt.hasNext())
- {
- TrustAnchor anchor = (TrustAnchor) trustIt.next();
- X509Certificate anchorCert = anchor.getTrustedCert();
- if (anchorCert != null)
- {
- if (anchorCert.getSubjectX500Principal().equals(
- cert.getIssuerX500Principal()))
- {
- try
- {
- cert.verify(anchorCert.getPublicKey(), "BC");
- trustAnchorFound = true;
- taCert = anchorCert;
- break;
- }
- catch (Exception e)
- {
- // trustanchor not found
- }
- }
- }
- else
- {
- if (anchor.getCAName().equals(
- cert.getIssuerX500Principal().getName()))
- {
- try
- {
- cert.verify(anchor.getCAPublicKey(), "BC");
- trustAnchorFound = true;
- break;
- }
- catch (Exception e)
- {
- // trustanchor not found
- }
- }
- }
- }
-
- if (!trustAnchorFound)
- {
- // add next cert to path
- X509CertSelector select = new X509CertSelector();
- try
- {
- select.setSubject(cert.getIssuerX500Principal().getEncoded());
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e.toString());
- }
- byte[] authKeyIdentBytes = cert.getExtensionValue(X509Extensions.AuthorityKeyIdentifier.getId());
- if (authKeyIdentBytes != null)
- {
- try
- {
- AuthorityKeyIdentifier kid = AuthorityKeyIdentifier.getInstance(getObject(authKeyIdentBytes));
- if (kid.getKeyIdentifier() != null)
- {
- select.setSubjectKeyIdentifier(new DEROctetString(kid.getKeyIdentifier()).getEncoded(ASN1Encoding.DER));
- }
- }
- catch (IOException ioe)
- {
- // ignore
- }
- }
- boolean userProvided = false;
-
- cert = findNextCert(systemCertStores, select, certSet);
- if (cert == null && userCertStores != null)
- {
- userProvided = true;
- cert = findNextCert(userCertStores, select, certSet);
- }
-
- if (cert != null)
- {
- // cert found
- certSet.add(cert);
- userProvidedList.add(new Boolean(userProvided));
- }
- }
- }
-
- // if a trustanchor was found - try to find a selfsigned certificate of
- // the trustanchor
- if (trustAnchorFound)
- {
- if (taCert != null && taCert.getSubjectX500Principal().equals(taCert.getIssuerX500Principal()))
- {
- certSet.add(taCert);
- userProvidedList.add(new Boolean(false));
- }
- else
- {
- X509CertSelector select = new X509CertSelector();
-
- try
- {
- select.setSubject(cert.getIssuerX500Principal().getEncoded());
- select.setIssuer(cert.getIssuerX500Principal().getEncoded());
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e.toString());
- }
-
- boolean userProvided = false;
-
- taCert = findNextCert(systemCertStores, select, certSet);
- if (taCert == null && userCertStores != null)
- {
- userProvided = true;
- taCert = findNextCert(userCertStores, select, certSet);
- }
- if (taCert != null)
- {
- try
- {
- cert.verify(taCert.getPublicKey(), "BC");
- certSet.add(taCert);
- userProvidedList.add(new Boolean(userProvided));
- }
- catch (GeneralSecurityException gse)
- {
- // wrong cert
- }
- }
- }
- }
-
- CertPath certPath = CertificateFactory.getInstance("X.509", "BC").generateCertPath(new ArrayList(certSet));
- return new Object[] {certPath, userProvidedList};
- }
-
- public CertStore getCertsAndCRLs()
- {
- return certs;
- }
-
- public SignerInformationStore getSignerInformationStore()
- {
- return signers;
- }
-
- public ValidationResult getValidationResult(SignerInformation signer)
- throws SignedMailValidatorException
- {
- if (signers.getSigners(signer.getSID()).isEmpty())
- {
- // the signer is not part of the SignerInformationStore
- // he has not signed the message
- ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
- "SignedMailValidator.wrongSigner");
- throw new SignedMailValidatorException(msg);
- }
- else
- {
- return (ValidationResult) results.get(signer);
- }
- }
-
- public class ValidationResult
- {
-
- private PKIXCertPathReviewer review;
-
- private List errors;
-
- private List notifications;
-
- private List userProvidedCerts;
-
- private boolean signVerified;
-
- ValidationResult(PKIXCertPathReviewer review, boolean verified,
- List errors, List notifications, List userProvidedCerts)
- {
- this.review = review;
- this.errors = errors;
- this.notifications = notifications;
- signVerified = verified;
- this.userProvidedCerts = userProvidedCerts;
- }
-
- /**
- * Returns a list of error messages of type {@link ErrorBundle}.
- *
- * @return List of error messages
- */
- public List getErrors()
- {
- return errors;
- }
-
- /**
- * Returns a list of notification messages of type {@link ErrorBundle}.
- *
- * @return List of notification messages
- */
- public List getNotifications()
- {
- return notifications;
- }
-
- /**
- *
- * @return the PKIXCertPathReviewer for the CertPath of this signature
- * or null if an Exception occured.
- */
- public PKIXCertPathReviewer getCertPathReview()
- {
- return review;
- }
-
- /**
- *
- * @return the CertPath for this signature
- * or null if an Exception occured.
- */
- public CertPath getCertPath()
- {
- return review != null ? review.getCertPath() : null;
- }
-
- /**
- *
- * @return a List of Booleans that are true if the corresponding certificate in the CertPath was taken from
- * the CertStore of the SMIME message
- */
- public List getUserProvidedCerts()
- {
- return userProvidedCerts;
- }
-
- /**
- *
- * @return true if the signature corresponds to the public key of the
- * signer
- */
- public boolean isVerifiedSignature()
- {
- return signVerified;
- }
-
- /**
- *
- * @return true if the signature is valid (ie. if it corresponds to the
- * public key of the signer and the cert path for the signers
- * certificate is also valid)
- */
- public boolean isValidSignature()
- {
- if (review != null)
- {
- return signVerified && review.isValidCertPath()
- && errors.isEmpty();
- }
- else
- {
- return false;
- }
- }
-
- }
-}