| package org.bouncycastle.jce.provider.test; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.math.BigInteger; |
| import java.net.InetAddress; |
| import java.net.UnknownHostException; |
| import java.security.InvalidKeyException; |
| import java.security.NoSuchAlgorithmException; |
| import java.security.NoSuchProviderException; |
| import java.security.Principal; |
| import java.security.Provider; |
| import java.security.PublicKey; |
| import java.security.Security; |
| import java.security.Signature; |
| import java.security.SignatureException; |
| import java.security.cert.CertPath; |
| import java.security.cert.CertPathValidator; |
| import java.security.cert.CertPathValidatorException; |
| import java.security.cert.CertStore; |
| import java.security.cert.CertStoreParameters; |
| import java.security.cert.Certificate; |
| import java.security.cert.CertificateEncodingException; |
| import java.security.cert.CertificateException; |
| import java.security.cert.CertificateExpiredException; |
| import java.security.cert.CertificateFactory; |
| import java.security.cert.CertificateNotYetValidException; |
| import java.security.cert.CertificateParsingException; |
| import java.security.cert.CollectionCertStoreParameters; |
| import java.security.cert.PKIXBuilderParameters; |
| import java.security.cert.PKIXCertPathChecker; |
| import java.security.cert.PKIXCertPathValidatorResult; |
| import java.security.cert.PKIXParameters; |
| import java.security.cert.PolicyNode; |
| import java.security.cert.TrustAnchor; |
| import java.security.cert.X509CRL; |
| import java.security.cert.X509CertSelector; |
| import java.security.cert.X509Certificate; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.Enumeration; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import javax.security.auth.x500.X500Principal; |
| |
| import org.bouncycastle.asn1.ASN1BitString; |
| import org.bouncycastle.asn1.ASN1Encodable; |
| import org.bouncycastle.asn1.ASN1Encoding; |
| import org.bouncycastle.asn1.ASN1InputStream; |
| import org.bouncycastle.asn1.ASN1ObjectIdentifier; |
| import org.bouncycastle.asn1.ASN1OutputStream; |
| import org.bouncycastle.asn1.ASN1Primitive; |
| import org.bouncycastle.asn1.ASN1Sequence; |
| import org.bouncycastle.asn1.ASN1String; |
| import org.bouncycastle.asn1.DERBitString; |
| import org.bouncycastle.asn1.DERIA5String; |
| import org.bouncycastle.asn1.DERNull; |
| import org.bouncycastle.asn1.DEROctetString; |
| import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; |
| import org.bouncycastle.asn1.misc.NetscapeCertType; |
| import org.bouncycastle.asn1.misc.NetscapeRevocationURL; |
| import org.bouncycastle.asn1.misc.VerisignCzagExtension; |
| import org.bouncycastle.asn1.util.ASN1Dump; |
| import org.bouncycastle.asn1.x500.X500Name; |
| import org.bouncycastle.asn1.x500.style.RFC4519Style; |
| import org.bouncycastle.asn1.x509.AlgorithmIdentifier; |
| import org.bouncycastle.asn1.x509.BasicConstraints; |
| import org.bouncycastle.asn1.x509.Extension; |
| import org.bouncycastle.asn1.x509.GeneralName; |
| import org.bouncycastle.asn1.x509.KeyUsage; |
| import org.bouncycastle.asn1.x509.X509CertificateStructure; |
| import org.bouncycastle.asn1.x509.X509Extension; |
| import org.bouncycastle.asn1.x509.X509Extensions; |
| import org.bouncycastle.jce.X509Principal; |
| import org.bouncycastle.jce.provider.BouncyCastleProvider; |
| import org.bouncycastle.util.Arrays; |
| import org.bouncycastle.util.Integers; |
| import org.bouncycastle.util.Strings; |
| import org.bouncycastle.util.encoders.Base64; |
| import org.bouncycastle.util.encoders.Hex; |
| import org.bouncycastle.util.test.SimpleTest; |
| |
| public class CertPathValidatorTest |
| extends SimpleTest |
| { |
| private byte[] AC_PR = Base64.decode( |
| "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlFU1RDQ0F6R2dBd0lC" |
| + "QWdJQkJUQU5CZ2txaGtpRzl3MEJBUVVGQURDQnRERUxNQWtHQTFVRUJoTUNR" |
| + "bEl4DQpFekFSQmdOVkJBb1RDa2xEVUMxQ2NtRnphV3d4UFRBN0JnTlZCQXNU" |
| + "TkVsdWMzUnBkSFYwYnlCT1lXTnBiMjVoDQpiQ0JrWlNCVVpXTnViMnh2WjJs" |
| + "aElHUmhJRWx1Wm05eWJXRmpZVzhnTFNCSlZFa3hFVEFQQmdOVkJBY1RDRUp5" |
| + "DQpZWE5wYkdsaE1Rc3dDUVlEVlFRSUV3SkVSakV4TUM4R0ExVUVBeE1vUVhW" |
| + "MGIzSnBaR0ZrWlNCRFpYSjBhV1pwDQpZMkZrYjNKaElGSmhhWG9nUW5KaGMy" |
| + "bHNaV2x5WVRBZUZ3MHdNakEwTURReE9UTTVNREJhRncwd05UQTBNRFF5DQpN" |
| + "elU1TURCYU1HRXhDekFKQmdOVkJBWVRBa0pTTVJNd0VRWURWUVFLRXdwSlEx" |
| + "QXRRbkpoYzJsc01UMHdPd1lEDQpWUVFERXpSQmRYUnZjbWxrWVdSbElFTmxj" |
| + "blJwWm1sallXUnZjbUVnWkdFZ1VISmxjMmxrWlc1amFXRWdaR0VnDQpVbVZ3" |
| + "ZFdKc2FXTmhNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJD" |
| + "Z0tDQVFFQXMwc0t5NGsrDQp6b016aldyMTQxeTVYQ045UGJMZERFQXN2cjZ4" |
| + "Z0NCN1l5bEhIQ1NBYmpGR3dOQ0R5NlVxN1h0VjZ6UHdIMXpGDQpFWENlS3Jm" |
| + "UUl5YXBXSEZ4V1VKajBMblFrY1RZM1FOR1huK0JuVk9EVTZDV3M1c3NoZktH" |
| + "RXZyVlQ1Z214V1NmDQp4OFlsdDgzY1dwUE1QZzg3VDlCaHVIbHQzazh2M2Ev" |
| + "NmRPbmF2dytOYTAyZExBaDBlNzZqcCtQUS9LK0pHZlBuDQphQjVVWURrZkd0" |
| + "em5uTTNBV01tY3VJK0o0ek5OMDZaa3ZnbDFsdEo2UU1qcnZEUFlSak9ndDlT" |
| + "cklpY1NmbEo4DQptVDdHWGRRaXJnQUNXc3g1QURBSklRK253TU1vNHlyTUtx" |
| + "SlFhNFFDMHhhT0QvdkdVcG9SaDQzT0FTZFp3c3YvDQpPWFlybmVJeVAwVCs4" |
| + "UUlEQVFBQm80RzNNSUcwTUQwR0ExVWRId1EyTURRd01xQXdvQzZHTEdoMGRI" |
| + "QTZMeTloDQpZM0poYVhvdWFXTndZbkpoYzJsc0xtZHZkaTVpY2k5TVExSmhZ" |
| + "M0poYVhvdVkzSnNNQklHQTFVZElBUUxNQWt3DQpCd1lGWUV3QkFRRXdIUVlE" |
| + "VlIwT0JCWUVGREpUVFlKNE9TWVB5T09KZkVMZXhDaHppK2hiTUI4R0ExVWRJ" |
| + "d1FZDQpNQmFBRklyNjhWZUVFUk0xa0VMNlYwbFVhUTJreFBBM01BNEdBMVVk" |
| + "RHdFQi93UUVBd0lCQmpBUEJnTlZIUk1CDQpBZjhFQlRBREFRSC9NQTBHQ1Nx" |
| + "R1NJYjNEUUVCQlFVQUE0SUJBUUJRUFNoZ1lidnFjaWV2SDVVb3ZMeXhkbkYr" |
| + "DQpFcjlOeXF1SWNkMnZ3Y0N1SnpKMkQ3WDBUcWhHQ0JmUEpVVkdBVWorS0NP" |
| + "SDFCVkgva1l1OUhsVHB1MGtKWFBwDQpBQlZkb2hJUERqRHhkbjhXcFFSL0Yr" |
| + "ejFDaWtVcldIMDR4eTd1N1p6UUpLSlBuR0loY1FpOElyRm1PYkllMEc3DQpY" |
| + "WTZPTjdPRUZxY21KTFFHWWdtRzFXMklXcytQd1JwWTdENGhLVEFoVjFSNkVv" |
| + "amE1L3BPcmVDL09kZXlQWmVxDQo1SUZTOUZZZk02U0Npd2hrK3l2Q1FHbVo0" |
| + "YzE5SjM0ZjVFYkRrK1NQR2tEK25EQ0E3L3VMUWNUMlJURE14SzBaDQpuZlo2" |
| + "Nm1Sc0ZjcXRGaWdScjVFcmtKZDdoUVV6eHNOV0VrNzJEVUFIcVgvNlNjeWtt" |
| + "SkR2V0plSUpqZlcNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg=="); |
| |
| private byte[] AC_RAIZ_ICPBRASIL = Base64.decode( |
| "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlFdURDQ0E2Q2dBd0lC" |
| + "QWdJQkJEQU5CZ2txaGtpRzl3MEJBUVVGQURDQnRERUxNQWtHQTFVRUJoTUNR" |
| + "bEl4DQpFekFSQmdOVkJBb1RDa2xEVUMxQ2NtRnphV3d4UFRBN0JnTlZCQXNU" |
| + "TkVsdWMzUnBkSFYwYnlCT1lXTnBiMjVoDQpiQ0JrWlNCVVpXTnViMnh2WjJs" |
| + "aElHUmhJRWx1Wm05eWJXRmpZVzhnTFNCSlZFa3hFVEFQQmdOVkJBY1RDRUp5" |
| + "DQpZWE5wYkdsaE1Rc3dDUVlEVlFRSUV3SkVSakV4TUM4R0ExVUVBeE1vUVhW" |
| + "MGIzSnBaR0ZrWlNCRFpYSjBhV1pwDQpZMkZrYjNKaElGSmhhWG9nUW5KaGMy" |
| + "bHNaV2x5WVRBZUZ3MHdNVEV4TXpBeE1qVTRNREJhRncweE1URXhNekF5DQpN" |
| + "elU1TURCYU1JRzBNUXN3Q1FZRFZRUUdFd0pDVWpFVE1CRUdBMVVFQ2hNS1NV" |
| + "TlFMVUp5WVhOcGJERTlNRHNHDQpBMVVFQ3hNMFNXNXpkR2wwZFhSdklFNWhZ" |
| + "Mmx2Ym1Gc0lHUmxJRlJsWTI1dmJHOW5hV0VnWkdFZ1NXNW1iM0p0DQpZV05o" |
| + "YnlBdElFbFVTVEVSTUE4R0ExVUVCeE1JUW5KaGMybHNhV0V4Q3pBSkJnTlZC" |
| + "QWdUQWtSR01URXdMd1lEDQpWUVFERXloQmRYUnZjbWxrWVdSbElFTmxjblJw" |
| + "Wm1sallXUnZjbUVnVW1GcGVpQkNjbUZ6YVd4bGFYSmhNSUlCDQpJakFOQmdr" |
| + "cWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBd1BNdWR3WC9odm0r" |
| + "VWgyYi9sUUFjSFZBDQppc2FtYUxrV2Rrd1A5L1MvdE9LSWdSckw2T3krWklH" |
| + "bE9VZGQ2dVl0azlNYS8zcFVwZ2NmTkFqMHZZbTVnc3lqDQpRbzllbXNjK3g2" |
| + "bTRWV3drOWlxTVpTQ0s1RVFrQXEvVXQ0bjdLdUxFMStnZGZ0d2RJZ3hmVXNQ" |
| + "dDRDeU5yWTUwDQpRVjU3S00yVVQ4eDVycm16RWpyN1RJQ0dwU1VBbDJnVnFl" |
| + "NnhhaWkrYm1ZUjFRcm1XYUJTQUc1OUxya3Jqcll0DQpiUmhGYm9VRGUxREsr" |
| + "NlQ4czVMNms4Yzhva3BiSHBhOXZlTXp0RFZDOXNQSjYwTVdYaDZhblZLbzFV" |
| + "Y0xjYlVSDQp5RWVOdlpuZVZSS0FBVTZvdXdkakR2d2xzYUt5ZEZLd2VkMFRv" |
| + "UTQ3Ym1VS2djbSt3VjNlVFJrMzZVT25Ud0lEDQpBUUFCbzRIU01JSFBNRTRH" |
| + "QTFVZElBUkhNRVV3UXdZRllFd0JBUUF3T2pBNEJnZ3JCZ0VGQlFjQ0FSWXNh" |
| + "SFIwDQpjRG92TDJGamNtRnBlaTVwWTNCaWNtRnphV3d1WjI5MkxtSnlMMFJR" |
| + "UTJGamNtRnBlaTV3WkdZd1BRWURWUjBmDQpCRFl3TkRBeW9EQ2dMb1lzYUhS" |
| + "MGNEb3ZMMkZqY21GcGVpNXBZM0JpY21GemFXd3VaMjkyTG1KeUwweERVbUZq" |
| + "DQpjbUZwZWk1amNtd3dIUVlEVlIwT0JCWUVGSXI2OFZlRUVSTTFrRUw2VjBs" |
| + "VWFRMmt4UEEzTUE4R0ExVWRFd0VCDQovd1FGTUFNQkFmOHdEZ1lEVlIwUEFR" |
| + "SC9CQVFEQWdFR01BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQVpBNWMxDQpV" |
| + "L2hnSWg2T2NnTEFmaUpnRldwdm1EWldxbFYzMC9iSEZwajhpQm9iSlNtNXVE" |
| + "cHQ3VGlyWWgxVXhlM2ZRYUdsDQpZakplKzl6ZCtpelBSYkJxWFBWUUEzNEVY" |
| + "Y3drNHFwV3VmMWhIcmlXZmRyeDhBY3FTcXI2Q3VRRndTcjc1Rm9zDQpTemx3" |
| + "REFEYTcwbVQ3d1pqQW1RaG5aeDJ4SjZ3ZldsVDlWUWZTLy9KWWVJYzdGdWUy" |
| + "Sk5MZDAwVU9TTU1haUsvDQp0NzllbktOSEVBMmZ1cEgzdkVpZ2Y1RWg0YlZB" |
| + "TjVWb2hyVG02TVk1M3g3WFFaWnIxTUU3YTU1bEZFblNlVDB1DQptbE9BalIy" |
| + "bUFidlNNNVg1b1NaTnJtZXRkenlUajJmbENNOENDN01MYWIwa2tkbmdSSWxV" |
| + "QkdIRjEvUzVubVBiDQpLKzlBNDZzZDMzb3FLOG44DQotLS0tLUVORCBDRVJU" |
| + "SUZJQ0FURS0tLS0tDQo="); |
| |
| private byte[] schefer = Base64.decode( |
| "MIIEnDCCBAWgAwIBAgICIPAwDQYJKoZIhvcNAQEEBQAwgcAxCzAJBgNVBAYT" |
| + "AkRFMQ8wDQYDVQQIEwZIRVNTRU4xGDAWBgNVBAcTDzY1MDA4IFdpZXNiYWRl" |
| + "bjEaMBgGA1UEChMRU0NIVUZBIEhPTERJTkcgQUcxGjAYBgNVBAsTEVNDSFVG" |
| + "QSBIT0xESU5HIEFHMSIwIAYDVQQDExlJbnRlcm5ldCBCZW51dHplciBTZXJ2" |
| + "aWNlMSowKAYJKoZIhvcNAQkBFht6ZXJ0aWZpa2F0QHNjaHVmYS1vbmxpbmUu" |
| + "ZGUwHhcNMDQwMzMwMTEwODAzWhcNMDUwMzMwMTEwODAzWjCBnTELMAkGA1UE" |
| + "BhMCREUxCjAIBgNVBAcTASAxIzAhBgNVBAoTGlNIUyBJbmZvcm1hdGlvbnNz" |
| + "eXN0ZW1lIEFHMRwwGgYDVQQLExM2MDAvMDU5NDktNjAwLzA1OTQ5MRgwFgYD" |
| + "VQQDEw9TY2hldHRlciBTdGVmYW4xJTAjBgkqhkiG9w0BCQEWFlN0ZWZhbi5T" |
| + "Y2hldHRlckBzaHMuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJD0" |
| + "95Bi76fkAMjJNTGPDiLPHmZXNsmakngDeS0juzKMeJA+TjXFouhYh6QyE4Bl" |
| + "Nf18fT4mInlgLefwf4t6meIWbiseeTo7VQdM+YrbXERMx2uHsRcgZMsiMYHM" |
| + "kVfYMK3SMJ4nhCmZxrBkoTRed4gXzVA1AA8YjjTqMyyjvt4TAgMBAAGjggHE" |
| + "MIIBwDAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIEsDALBgNVHQ8EBAMC" |
| + "BNAwOQYJYIZIAYb4QgENBCwWKlplcnRpZmlrYXQgbnVyIGZ1ZXIgU0NIVUZB" |
| + "LU9ubGluZSBndWVsdGlnLjAdBgNVHQ4EFgQUXReirhBfg0Yhf6MsBWoo/nPa" |
| + "hGwwge0GA1UdIwSB5TCB4oAUf2UyCaBV9JUeG9lS1Yo6OFBUdEKhgcakgcMw" |
| + "gcAxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZIRVNTRU4xGDAWBgNVBAcTDzY1" |
| + "MDA4IFdpZXNiYWRlbjEaMBgGA1UEChMRU0NIVUZBIEhPTERJTkcgQUcxGjAY" |
| + "BgNVBAsTEVNDSFVGQSBIT0xESU5HIEFHMSIwIAYDVQQDExlJbnRlcm5ldCBC" |
| + "ZW51dHplciBTZXJ2aWNlMSowKAYJKoZIhvcNAQkBFht6ZXJ0aWZpa2F0QHNj" |
| + "aHVmYS1vbmxpbmUuZGWCAQAwIQYDVR0RBBowGIEWU3RlZmFuLlNjaGV0dGVy" |
| + "QHNocy5kZTAmBgNVHRIEHzAdgRt6ZXJ0aWZpa2F0QHNjaHVmYS1vbmxpbmUu" |
| + "ZGUwDQYJKoZIhvcNAQEEBQADgYEAWzZtN9XQ9uyrFXqSy3hViYwV751+XZr0" |
| + "YH5IFhIS+9ixNAu8orP3bxqTaMhpwoU7T/oSsyGGSkb3fhzclgUADbA2lrOI" |
| + "GkeB/m+FArTwRbwpqhCNTwZywOp0eDosgPjCX1t53BB/m/2EYkRiYdDGsot0" |
| + "kQPOVGSjQSQ4+/D+TM8="); |
| |
| // circular dependency certificates |
| private static final byte[] circCA = Base64.decode( |
| "MIIDTzCCAjegAwIBAgIDARAAMA0GCSqGSIb3DQEBBQUAMDkxCzAJBgNVBAYT" |
| + "AkZSMRAwDgYDVQQKEwdHSVAtQ1BTMRgwFgYDVQQLEw9HSVAtQ1BTIEFOT05Z" |
| + "TUUwHhcNMDQxMDExMDAwMDAxWhcNMTQxMjMxMjM1OTU5WjA5MQswCQYDVQQG" |
| + "EwJGUjEQMA4GA1UEChMHR0lQLUNQUzEYMBYGA1UECxMPR0lQLUNQUyBBTk9O" |
| + "WU1FMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3WyWDwcM58aU" |
| + "hPX4ueI1mwETt3WdQtMfIdRiCXeBrjCkYCc7nIgCmGbnfTzXSplHRgKColWh" |
| + "q/Z+1rHYayje1gjAEU2+4/r1P2pnBmPgquDuguktCIbDtCcGZu0ylyKeHh37" |
| + "aeIKzkcmRSLRzvGf/eO3RdFksrvaPaSjqCVfGRXVDKK2uftE8rIFJE+bCqow" |
| + "6+WiaAaDDiJaSJPuu5hC1NA5jw0/BFodlCuAvl1GJ8A+TICkYWcSpKS9bkSC" |
| + "0i8xdGbSSk94shA1PdDvRdFMfFys8g4aupBXV8yqqEAUkBYmOtZSJckc3W4y" |
| + "2Gx53y7vY07Xh63mcgtJs2T82WJICwIDAQABo2AwXjAdBgNVHQ4EFgQU8c/P" |
| + "NNJaL0srd9SwHwgtvwPB/3cwDgYDVR0PAQH/BAQDAgIEMBkGA1UdIAQSMBAw" |
| + "DgYMKoF6AUcDBwgAAAABMBIGA1UdEwEB/wQIMAYBAf8CAQEwDQYJKoZIhvcN" |
| + "AQEFBQADggEBAHRjYDPJKlfUzID0YzajZpgR/i2ngJrJqYeaWCmwzBgNUPad" |
| + "uBKSGHmPVg21sfULMSnirnR+e90i/D0EVzLwQzcbjPDD/85rp9QDCeMxqqPe" |
| + "9ZCHGs2BpE/HOQMP0QfQ3/Kpk7SvOH/ZcpIf6+uE6lLBQYAGs5cxvtTGOzZk" |
| + "jCVFG+TrAnF4V5sNkn3maCWiYLmyqcnxtKEFSONy2bYqqudx/dBBlRrDbRfZ" |
| + "9XsCBdiXAHY1hFHldbfDs8rslmkXJi3fJC028HZYB6oiBX/JE7BbMk7bRnUf" |
| + "HSpP7Sjxeso2SY7Yit+hQDVAlqTDGmh6kLt/hQMpsOMry4vgBL6XHKw="); |
| |
| private static final byte[] circCRLCA = Base64.decode( |
| "MIIDXDCCAkSgAwIBAgIDASAAMA0GCSqGSIb3DQEBBQUAMDkxCzAJBgNVBAYT" |
| + "AkZSMRAwDgYDVQQKEwdHSVAtQ1BTMRgwFgYDVQQLEw9HSVAtQ1BTIEFOT05Z" |
| + "TUUwHhcNMDQxMDExMDAwMDAxWhcNMTQxMjMxMjM1OTU5WjA5MQswCQYDVQQG" |
| + "EwJGUjEQMA4GA1UEChMHR0lQLUNQUzEYMBYGA1UECxMPR0lQLUNQUyBBTk9O" |
| + "WU1FMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwfEcFK0g7Kfo" |
| + "o5f2IBF7VEd/AG+RVGSds0Yg+u2kNYu4k04HR/+tOdBQtJvyr4W5jrQKsC5X" |
| + "skeFWMyWaFKzAjZDWB52HWp/kiMivGcxnYDuYf5piukSC+d2+vL8YaAphDzV" |
| + "HPnxEKqoM/J66uUussDTqfcL3JC/Bc7kBwn4srrsZOsamMWTQQtEqVQxNN7A" |
| + "ROSRsdiTt3hMOKditc9/NBNmjZWxgc7Twr/SaZ8CfN5wf2wuOl23knWL0QsJ" |
| + "0lSMBSBTzTcfAke4/jIT7d4nVMp3t7dsna8rt56pFK4wpRFGuCt+1P5gi51x" |
| + "xVSdI+JoNXv6zGO4o8YVaRpC5rQeGQIDAQABo20wazAfBgNVHSMEGDAWgBTx" |
| + "z8800lovSyt31LAfCC2/A8H/dzAdBgNVHQ4EFgQUGa3SbBrJx/wa2MQwhWPl" |
| + "dwLw1+IwDgYDVR0PAQH/BAQDAgECMBkGA1UdIAQSMBAwDgYMKoF6AUcDBwgA" |
| + "AAABMA0GCSqGSIb3DQEBBQUAA4IBAQAPDpYe2WPYnXTLsXSIUREBNMLmg+/7" |
| + "4Yhq9uOm5Hb5LVkDuHoEHGfmpXXEvucx5Ehu69hw+F4YSrd9wPjOiG8G6GXi" |
| + "RcrK8nE8XDvvV+E1HpJ7NKN4fSAoSb+0gliiq3aF15bvXP8nfespdd/x1xWQ" |
| + "mpYCx/mJeuqONQv2/D/7hfRKYoDBaAkWGodenPFPVs6FxwnEuH2R+KWCUdA9" |
| + "L04v8JBeL3kZiALkU7+DCCm7A0imUAgeeArbAbfIPu6eDygm+XndZ9qi7o4O" |
| + "AntPxrqbeXFIbDrQ4GV1kpxnW+XpSGDd96SWKe715gxkkDBppR5IKYJwRb6O" |
| + "1TRQIf2F+muQ"); |
| |
| private static final byte[] circCRL = Base64.decode( |
| "MIIB1DCBvQIBATANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGUjEQMA4G" |
| + "A1UEChMHR0lQLUNQUzEYMBYGA1UECxMPR0lQLUNQUyBBTk9OWU1FFw0xMDAx" |
| + "MDcwMzAwMTVaFw0xMDAxMTMwMzAwMTVaMACgTjBMMB8GA1UdIwQYMBaAFBmt" |
| + "0mwaycf8GtjEMIVj5XcC8NfiMAsGA1UdFAQEAgILgzAcBgNVHRIEFTATgRFh" |
| + "Yy1naXBAZ2lwLWNwcy5mcjANBgkqhkiG9w0BAQUFAAOCAQEAtF1DdFl1MQvf" |
| + "vNkbrCPuppNYcHen4+za/ZDepKuwHsH/OpKuaDJc4LndRgd5IwzfpCHkQGzt" |
| + "shK50bakN8oaYJgthKIOIJzR+fn6NMjftfR2a27Hdk2o3eQXRHQ360qMbpSy" |
| + "qPb3WfuBhxO2/DlLChJP+OxZIHtT/rNYgE0tlIv7swYi81Gq+DafzaZ9+A5t" |
| + "I0L2Gp/NUDsp5dF6PllAGiXQzl27qkcu+r50w+u0gul3nobXgbwPcMSYuWUz" |
| + "1lhA+uDn/EUWV4RSiJciCGSS10WCkFh1/YPo++mV15KDB0m+8chscrSu/bAl" |
| + "B19LxL/pCX3qr5iLE9ss3olVImyFZg=="); |
| |
| private void checkCircProcessing() |
| throws Exception |
| { |
| CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); |
| |
| X509Certificate caCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(circCA)); |
| X509Certificate crlCaCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(circCRLCA)); |
| X509CRL crl = (X509CRL)cf.generateCRL(new ByteArrayInputStream(circCRL)); |
| |
| List list = new ArrayList(); |
| |
| list.add(caCert); |
| list.add(crlCaCert); |
| list.add(crl); |
| |
| CertStoreParameters ccsp = new CollectionCertStoreParameters(list); |
| CertStore store = CertStore.getInstance("Collection", ccsp); |
| |
| Date validDate = new Date(crl.getThisUpdate().getTime() + 60 * 60 * 1000); |
| |
| //validating path |
| List certchain = new ArrayList(); |
| |
| certchain.add(crlCaCert); |
| CertPath cp = CertificateFactory.getInstance("X.509", "BC").generateCertPath(certchain); |
| |
| Set trust = new HashSet(); |
| trust.add(new TrustAnchor(caCert, null)); |
| |
| CertPathValidator cpv = CertPathValidator.getInstance("PKIX", "BC"); |
| //PKIXParameters param = new PKIXParameters(trust); |
| |
| PKIXBuilderParameters param = new PKIXBuilderParameters(trust, null); |
| X509CertSelector certSelector = new X509CertSelector(); |
| certSelector.setCertificate(crlCaCert); |
| param.setTargetCertConstraints(certSelector); |
| param.addCertStore(store); |
| param.setRevocationEnabled(true); |
| param.setDate(validDate); |
| |
| PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult)cpv.validate(cp, param); |
| } |
| |
| private void checkPolicyProcessingAtDomainMatch() |
| throws Exception |
| { |
| CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); |
| |
| X509Certificate root = (X509Certificate)cf.generateCertificate(this.getClass().getResourceAsStream("qvRooCa3.crt")); |
| X509Certificate ca1 = (X509Certificate)cf.generateCertificate(this.getClass().getResourceAsStream("suvaRoot1.crt")); |
| X509Certificate ca2 = (X509Certificate)cf.generateCertificate(this.getClass().getResourceAsStream("suvaEmail1.crt")); |
| X509Certificate ee = (X509Certificate)cf.generateCertificate(this.getClass().getResourceAsStream("suvaEE.crt")); |
| |
| List certchain = new ArrayList(); |
| certchain.add(ee); |
| certchain.add(ca2); |
| certchain.add(ca1); |
| |
| Set trust = new HashSet(); |
| trust.add(new TrustAnchor(root, null)); |
| |
| CertPathValidator cpv = CertPathValidator.getInstance("PKIX", "BC"); |
| PKIXParameters param = new PKIXParameters(trust); |
| param.setRevocationEnabled(false); |
| param.setDate(new Date(0x156445410b4L)); // around 1st August 2016 |
| |
| CertPath cp = cf.generateCertPath(certchain); |
| |
| MyChecker checker = new MyChecker(); |
| param.addCertPathChecker(checker); |
| |
| PKIXCertPathValidatorResult result = |
| (PKIXCertPathValidatorResult)cpv.validate(cp, param); |
| } |
| |
| public void testEmptyPath() |
| throws Exception |
| { |
| CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); |
| X509Certificate rootCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(CertPathTest.rootCertBin)); |
| |
| List list = new ArrayList(); |
| list.add(rootCert); |
| CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(list); |
| CertStore store = CertStore.getInstance("Collection", ccsp, "BC"); |
| |
| List certchain = new ArrayList(); |
| CertPath cp = CertificateFactory.getInstance("X.509", "BC").generateCertPath(certchain); |
| Set trust = new HashSet(); |
| trust.add(new TrustAnchor(rootCert, null)); |
| |
| CertPathValidator cpv = CertPathValidator.getInstance("PKIX", "BC"); |
| PKIXParameters param = new PKIXParameters(trust); |
| param.addCertStore(store); |
| MyChecker checker = new MyChecker(); |
| param.addCertPathChecker(checker); |
| |
| try |
| { |
| cpv.validate(cp, param); |
| } |
| catch (CertPathValidatorException e) |
| { |
| if (!"Certification path is empty.".equals(e.getMessage())) |
| { |
| fail("message mismatch"); |
| } |
| } |
| } |
| |
| public void performTest() |
| throws Exception |
| { |
| CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); |
| |
| // initialise CertStore |
| X509Certificate rootCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(CertPathTest.rootCertBin)); |
| X509Certificate interCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(CertPathTest.interCertBin)); |
| X509Certificate finalCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(CertPathTest.finalCertBin)); |
| X509CRL rootCrl = (X509CRL)cf.generateCRL(new ByteArrayInputStream(CertPathTest.rootCrlBin)); |
| X509CRL interCrl = (X509CRL)cf.generateCRL(new ByteArrayInputStream(CertPathTest.interCrlBin)); |
| List list = new ArrayList(); |
| list.add(rootCert); |
| list.add(interCert); |
| list.add(finalCert); |
| list.add(rootCrl); |
| list.add(interCrl); |
| CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(list); |
| CertStore store = CertStore.getInstance("Collection", ccsp, "BC"); |
| Date validDate = new Date(rootCrl.getThisUpdate().getTime() + 60 * 60 * 1000); |
| //validating path |
| List certchain = new ArrayList(); |
| certchain.add(finalCert); |
| certchain.add(interCert); |
| |
| CertPath cp = CertificateFactory.getInstance("X.509", "BC").generateCertPath(certchain); |
| Set trust = new HashSet(); |
| trust.add(new TrustAnchor(rootCert, null)); |
| |
| CertPathValidator cpv = CertPathValidator.getInstance("PKIX", "BC"); |
| PKIXParameters param = new PKIXParameters(trust); |
| param.addCertStore(store); |
| param.setDate(validDate); |
| MyChecker checker = new MyChecker(); |
| param.addCertPathChecker(checker); |
| |
| PKIXCertPathValidatorResult result = |
| (PKIXCertPathValidatorResult)cpv.validate(cp, param); |
| PolicyNode policyTree = result.getPolicyTree(); |
| PublicKey subjectPublicKey = result.getPublicKey(); |
| |
| if (checker.getCount() != 2) |
| { |
| fail("checker not evaluated for each certificate"); |
| } |
| |
| if (!subjectPublicKey.equals(finalCert.getPublicKey())) |
| { |
| fail("wrong public key returned"); |
| } |
| |
| isTrue(result.getTrustAnchor().getTrustedCert().equals(rootCert)); |
| |
| // try a path with trust anchor included. |
| certchain.clear(); |
| certchain.add(finalCert); |
| certchain.add(interCert); |
| certchain.add(rootCert); |
| |
| cp = CertificateFactory.getInstance("X.509", "BC").generateCertPath(certchain); |
| |
| cpv = CertPathValidator.getInstance("PKIX", "BC"); |
| param = new PKIXParameters(trust); |
| param.addCertStore(store); |
| param.setDate(validDate); |
| |
| result = (PKIXCertPathValidatorResult)cpv.validate(cp, param); |
| |
| isTrue(result.getTrustAnchor().getTrustedCert().equals(rootCert)); |
| |
| // |
| // invalid path containing a valid one test |
| // |
| try |
| { |
| // initialise CertStore |
| rootCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(AC_RAIZ_ICPBRASIL)); |
| interCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(AC_PR)); |
| finalCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(schefer)); |
| |
| list = new ArrayList(); |
| list.add(rootCert); |
| list.add(interCert); |
| list.add(finalCert); |
| |
| ccsp = new CollectionCertStoreParameters(list); |
| store = CertStore.getInstance("Collection", ccsp); |
| validDate = new Date(finalCert.getNotBefore().getTime() + 60 * 60 * 1000); |
| |
| //validating path |
| certchain = new ArrayList(); |
| certchain.add(finalCert); |
| certchain.add(interCert); |
| |
| cp = CertificateFactory.getInstance("X.509", "BC").generateCertPath(certchain); |
| trust = new HashSet(); |
| trust.add(new TrustAnchor(rootCert, null)); |
| |
| cpv = CertPathValidator.getInstance("PKIX", "BC"); |
| param = new PKIXParameters(trust); |
| param.addCertStore(store); |
| param.setRevocationEnabled(false); |
| param.setDate(validDate); |
| |
| result = (PKIXCertPathValidatorResult)cpv.validate(cp, param); |
| policyTree = result.getPolicyTree(); |
| subjectPublicKey = result.getPublicKey(); |
| |
| fail("Invalid path validated"); |
| } |
| catch (Exception e) |
| { |
| if (!(e instanceof CertPathValidatorException |
| && e.getMessage().startsWith("Could not validate certificate signature."))) |
| { |
| fail("unexpected exception", e); |
| } |
| } |
| |
| checkCircProcessing(); |
| checkPolicyProcessingAtDomainMatch(); |
| validateWithExtendedKeyUsage(); |
| testEmptyPath(); |
| checkInvalidCertPath(); |
| } |
| |
| // extended key usage chain |
| static byte[] extEE = Base64.decode("MIICtDCCAh2gAwIBAgIBAzANBgkqhkiG9w0BAQUFADCBkjELMAkGA1UEBhMCQVUxKDAmBgNVBAoMH1RoZSBMZWdpb24gb2YgdGhlIEJvdW5jeSBDYXN0bGUxKDAmBgNVBAsMH0JvdW5jeSBJbnRlcm1lZGlhdGUgQ2VydGlmaWNhdGUxLzAtBgkqhkiG9w0BCQEWIGZlZWRiYWNrLWNyeXB0b0Bib3VuY3ljYXN0bGUub3JnMB4XDTE1MDMyNDAzNTEwOVoXDTE1MDUyMzAzNTEwOVowgZYxCzAJBgNVBAYTAkFVMSgwJgYDVQQKDB9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIwEAYDVQQHDAlNZWxib3VybmUxGDAWBgNVBAMMD0VyaWMgSC4gRWNoaWRuYTEvMC0GCSqGSIb3DQEJARYgZmVlZGJhY2stY3J5cHRvQGJvdW5jeWNhc3RsZS5vcmcwWjANBgkqhkiG9w0BAQEFAANJADBGAkEAtKfkYXBXTxapcIKyK+WLaipil5hBm+EocqS9umJs+umQD3ar+xITnc5d5WVk+rK2VDFloEDGBoh0IOM9ke1+1wIBEaNaMFgwHQYDVR0OBBYEFNBs7G01g7xVEhsMyz7+1yamFmRoMB8GA1UdIwQYMBaAFJQIM28yQPeHN9rRIKrtLqduyckeMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBBQUAA4GBAICrsNswvaXFMreUHHRHrhU4QqPOds8XJe0INx3v/5TfyjPPDMihMEm8WtWbVpFgFAqUQoZscf8cE/SO5375unYFgxrK+p2/je9E82VLF4Xb0cWizjQoWvvTmvFYjt43cGGXgySFLTrW87ju9uNFr/l4W9xvI0hoLI96vEW7Ccho"); |
| static byte[] extCA = Base64.decode("MIIDIzCCAoygAwIBAgIBAjANBgkqhkiG9w0BAQUFADBcMQswCQYDVQQGEwJBVTEoMCYGA1UECgwfVGhlIExlZ2lvbiBvZiB0aGUgQm91bmN5IENhc3RsZTEjMCEGA1UECwwaQm91bmN5IFByaW1hcnkgQ2VydGlmaWNhdGUwHhcNMTUwMzI0MDM1MTA5WhcNMTUwNTIzMDM1MTA5WjCBkjELMAkGA1UEBhMCQVUxKDAmBgNVBAoMH1RoZSBMZWdpb24gb2YgdGhlIEJvdW5jeSBDYXN0bGUxKDAmBgNVBAsMH0JvdW5jeSBJbnRlcm1lZGlhdGUgQ2VydGlmaWNhdGUxLzAtBgkqhkiG9w0BCQEWIGZlZWRiYWNrLWNyeXB0b0Bib3VuY3ljYXN0bGUub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCN4NETxec2lpyNKwR6JD+P4Y7a1kzenoQtNmkjDKSG98/d4fjuxU0ZBf/wSsyF5hCT4YDK3GzqQH8ZPUS7DpRJuNu0l4TNnjYmDDngapRymZeMbtgwByTohxmM/t4g8/veZY+ivQeL6Uajkr00nytJxIbiDEBViOMGcGyQFzCOaQIDAP//o4G9MIG6MB0GA1UdDgQWBBSUCDNvMkD3hzfa0SCq7S6nbsnJHjCBhAYDVR0jBH0we4AUwDYZB63EiJeoXnJvawnr5ebxKVyhYKReMFwxCzAJBgNVBAYTAkFVMSgwJgYDVQQKDB9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMSMwIQYDVQQLDBpCb3VuY3kgUHJpbWFyeSBDZXJ0aWZpY2F0ZYIBATASBgNVHRMBAf8ECDAGAQH/AgEAMA0GCSqGSIb3DQEBBQUAA4GBAJqUlDjse7Og+7qkkFsiXHzQ8FxT82hzfcji8W7bPwZddCPBEluxCJiJBPYXWsLvwo6BEmCDzT9lLQZ+QZyL1fVbOVHiI24hAalbEBEIrEO4GXMD9spqRQ5yoTJ8CgZHTPo0rJkH/ebprp0YHtahVF440zBOvuLM0QTYpERgO2Oe"); |
| static byte[] extTrust = Base64.decode("MIICJTCCAY4CAQEwDQYJKoZIhvcNAQEFBQAwXDELMAkGA1UEBhMCQVUxKDAmBgNVBAoMH1RoZSBMZWdpb24gb2YgdGhlIEJvdW5jeSBDYXN0bGUxIzAhBgNVBAsMGkJvdW5jeSBQcmltYXJ5IENlcnRpZmljYXRlMB4XDTE1MDMyNDAzNTEwOVoXDTE1MDUyMzAzNTEwOVowXDELMAkGA1UEBhMCQVUxKDAmBgNVBAoMH1RoZSBMZWdpb24gb2YgdGhlIEJvdW5jeSBDYXN0bGUxIzAhBgNVBAsMGkJvdW5jeSBQcmltYXJ5IENlcnRpZmljYXRlMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCyWdLW5ienaMlL42Fkwtn8edl6q5JTFA5b8XdRGXcx1vdUDSUJ57n/7gpwpuJtVuktLt1/hauoVgC2kInzX2vb88KY4FhCU12fBk5rA5HLfTBuCi0gxN+057SalkC96ibBCtacPwUAfOJRPO5Ez+AZmOYrbDY30/wDkQebJu421QIBETANBgkqhkiG9w0BAQUFAAOBgQCDNfqQnQbbmnGzZTl7ccWIyw7SPzWnijpKsQpuRNGkoXfkCcuQLZudytEFZGEL0cycNBnierjJWAn78zGpCQtab01r1GwytRMYz8qO5IIrhsJ4XNafNypYZbi0WtPa07UCQp8tipMbfQNLzSkvkIAaD5IfhdaWKLrSQJwmGg7YAg=="); |
| |
| private void validateWithExtendedKeyUsage() |
| throws Exception |
| { |
| CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); |
| |
| X509Certificate rootCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(extTrust)); |
| X509Certificate interCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(extCA)); |
| X509Certificate finalCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(extEE)); |
| |
| List list = new ArrayList(); |
| list.add(rootCert); |
| list.add(interCert); |
| list.add(finalCert); |
| |
| CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(list); |
| CertStore store = CertStore.getInstance("Collection", ccsp, "BC"); |
| Date validDate = new Date(rootCert.getNotBefore().getTime() + 60 * 60 * 1000); |
| //validating path |
| List certchain = new ArrayList(); |
| certchain.add(finalCert); |
| certchain.add(interCert); |
| CertPath cp = CertificateFactory.getInstance("X.509", "BC").generateCertPath(certchain); |
| Set trust = new HashSet(); |
| trust.add(new TrustAnchor(rootCert, null)); |
| |
| CertPathValidator cpv = CertPathValidator.getInstance("PKIX", "BC"); |
| PKIXParameters param = new PKIXParameters(trust); |
| param.addCertStore(store); |
| param.setDate(validDate); |
| param.setRevocationEnabled(false); |
| |
| PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult)cpv.validate(cp, param); |
| } |
| |
| // invalid EE certificate |
| static byte[] extInvEE = Base64.decode("MIICJjCCAY+gAwIBAAIGAV3Y0TnDMA0GCSqGSIb3DQEBCwUAMBExDzANBgNVBAMMBktQMSBDQTAeFw0xNzA4MTIyMzM5MzJaFw0xNzA4MTMwMDA5MzdaMBExDzANBgNVBAMMBktQMSBFRTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuOcqkp2+HBCuwRDwfR7kkUYXMdhScDG8m6A3Af6hpG86nAimNoVIQe3REaQ6IO0XSdd13rjjRwIXsUFLsrQhQJczF5JeyWXcaYqZyNNbUwFuLeSqOsLS63ltjOJYqOJRxY03Cr//baGWvxGXcRvHoZkg1nEXPcMZhgsy/9JxVoUCAwEAAaOBiDCBhTBABgNVHSMEOTA3gBSPMqzNmTdyjQmr9W1TSDW1h0ZzFaEXpBUwEzERMA8GA1UEAwwIS1AxIFJPT1SCBgFd2NE5wjAdBgNVHQ4EFgQUC1rtYrQdQkA3CLTeV1kbVIdysKQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADgYEAGr841G7E84Ow9+fFGW1zzXeTRfxsafdT/bHXCS75bjF2YPitKLcRLkm92VPxANRXIpmt++3iU/oduWqkLsfXnfTGmCwtjj/XrCvkCBQ4GONwmegltJEThMud0XOEB1UN6tfTINfLYpbyfOdE/wLy4Rte0t43aOTTOBo+/SapYOE="); |
| static byte[] extInvCA = Base64.decode("MIICKDCCAZGgAwIBAgIGAV3Y0TnCMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCEtQMSBST09UMB4XDTE3MDgxMjIzMzkzMloXDTE3MDgxMzAwMDkzN1owETEPMA0GA1UEAwwGS1AxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7Qd/cTP5S0GoPcomcZU5QlJcb1uWydvmQx3U6p4/KOZBhk6JXQeSzT8QZ/gd+9vfosA62SEX+dq7MvxxzeERxdIsVU0zZ1TrYNxlQjnYXiYRVXBczowsxseQ9oSGD94Y4buhrMAltmIHijdzGRVMY41FZmWqNXqsEwQXj6ULX+QIDAQABo4GIMIGFMEAGA1UdIwQ5MDeAFAbfd2S3aiwFww3/0ocLa6ULQjJMoRekFTATMREwDwYDVQQDDAhLUDEgUk9PVIIGAV3Y0TnBMB0GA1UdDgQWBBSPMqzNmTdyjQmr9W1TSDW1h0ZzFTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOBgQCnmxQYy6LnvRSMxkTsGIQa4LB51O8skbWc4KYVDfcvTYQuvn6rE/ZoYf82jKXJzXksffanfjn/b38l4l8hwAcBQ8we9yjCkjO8OVDUlYiSGYUhH2ZJrl2+K2Z6wpakZ9Lz3pZ/PSS1FIsVd4I1jkexAdAm1+uMlfWXVt/uTZx98w=="); |
| static byte[] extInvTrust = Base64.decode("MIIBmjCCAQMCBgFd2NE5wTANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhLUDEgUk9PVDAeFw0xNzA4MTIyMzM5MzJaFw0xNzA4MTMwMDA5MzdaMBMxETAPBgNVBAMMCEtQMSBST09UMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8U3p6Y9ah0yQ58wpI3H6vQPMdhN6Hh+zuiNzwX3AIpEspUFTfqXJ6EIhqh/EraDnLnoFBajzihwS1y6a+ZyXYKa5pxbFsslmzms+ozcTaJ4mSMiC+DHbGYdOAEzwx2nsEt7UKyrlnl5h2kQFusUPmnXXEorIxhpS2Lul+zEBo1wIDAQABMA0GCSqGSIb3DQEBCwUAA4GBABClwXaJ8S66GmeySf1thOPc1GxIHuubezIjcBbECLZQqn7iwuzp+eft1vtnqNP7BWM1xBZkSe+/2xUsArc1rb1ffZHF3k92+WLbpDh3+NsQIod/91HRWUuu/S2g9oMK4b7BH8JrmBgy3ewtpNZwOaKF613GPCeGv3ya5Z24vBu+"); |
| |
| static byte[] extInvV2Trust = Base64.decode("MIIBmjCCAQMCBgFd2NhVgTANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhLUDEgUk9PVDAeFw0xNzA4MTIyMzQ3MThaFw0xNzA4MTMwMDE3MjNaMBMxETAPBgNVBAMMCEtQMSBST09UMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQaASWM5avAAJ57eHQ2zQ0k/mAiYSOkRKDLEzptDPYfzuQtTdAlBPn7tsYx+Ylge4YQwtx5bQZbc3apinBK9tn+c++go0kUF1cec2bacYyFokSP2r48j6ZhlY4MYGfrvfWHULrG2JL2BMeuZVP+wiqXktXCEKVG1fh1m6RY0TJPwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAC9mXO2i2vltBZZa7RMkizvhzhsehDHbEqvJd2aoWE9JG4sDo2tiIVN5vbq9EWLZVga3ejFzmQ+FI1Ty0xX3fwDgvUyxsveGTs40xwA9TEgVk1KNTQQs+sLE9rRB7L0giKn2DDmHFsOPL1KwxdzqD7vYhJr5av3eAsJpMxF+Anyg"); |
| static byte[] extInvV2CA = Base64.decode("MIICKDCCAZGgAwIBAgIGAV3Y2FWCMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCEtQMSBST09UMB4XDTE3MDgxMjIzNDcxOFoXDTE3MDgxMzAwMTcyM1owETEPMA0GA1UEAwwGS1AxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCgb8h3h9d/FzhIc+PMbF0vwdiDKw7N3dNyY6TrmzCMC1mYDXSKmxxDwNKZCKj6VSNfbTDqxYKlZMoGVT8Cl/iE/+XEhOKYLv73rzTqzdMizqcQTCvwps1enGxI5wPBYKGCMWrpJui5RWV9wH6hMvmzSSZq7bdWTvc/pIltCpIj8wIDAQABo4GIMIGFMEAGA1UdIwQ5MDeAFMOcs/uWpVOkGRQJrVIp6cN6tCJQoRekFTATMREwDwYDVQQDDAhLUDEgUk9PVIIGAV3Y2FWBMB0GA1UdDgQWBBTsZ2B5JbgKm9/up2hOcYVyOaM1SjASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOBgQBI8J1bKh/e+uEZtfngKMADS1PSHztAPFFKXgeIfYeJDRznnamtbheensdxrA+aoriJbJfHxmjecr4xA8+s0uN9GPtQ3+ad1K5Sg6mfzsXtNPf3xa9y0pIWOGZavr1s/QugoPLQxEiuHrvkHX5+sZlx47KoBQJ8LBRmJydeSvxz1g=="); |
| static byte[] extInvV2EE = Base64.decode("MIICJjCCAY+gAwIBAQIGAV3Y2FWDMA0GCSqGSIb3DQEBCwUAMBExDzANBgNVBAMMBktQMSBDQTAeFw0xNzA4MTIyMzQ3MThaFw0xNzA4MTMwMDE3MjNaMBExDzANBgNVBAMMBktQMSBFRTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzWXxtMpnjz8Q1qTdwpB66W2D0vEHhqow2PTsvfQdENL4AFESE1C7Cj3lLBTei1vRHCnpM0jdNghBW8k/u2b2tqeeWLBqwul0tEGbjtUwkYV2WgtTGmiYZZFfMH35HIvqlZMwIIdZqz4lEdkPiAPEUOELvycpVDFnWjF0qah5LqsCAwEAAaOBiDCBhTBABgNVHSMEOTA3gBTsZ2B5JbgKm9/up2hOcYVyOaM1SqEXpBUwEzERMA8GA1UEAwwIS1AxIFJPT1SCBgFd2NhVgjAdBgNVHQ4EFgQUfeKdn63Gmlkub8m8bwjqJook5ywwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADgYEAco35KYLE683l53J6V1q2tcMV3EpM39tifkL7Kl38oX9d3SGiKkEO6YFeQekRyto0Z91mPq7Pe/oOfDrfsY3r9KX7oqnhOKBnnR/58atM9udVLvuLfCJpxiroAldSkhRKvHG5MrFwZyDcVkTZF4GDrP6bojp32wVfU5EYkfwcJN8="); |
| |
| static byte[] extInvVersionTrust = Base64.decode("MIIBmjCCAQMCBgFd2RZiPjANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhLUDEgUk9PVDAeFw0xNzA4MTMwMDU1MDRaFw0xNzA4MTMwMTI1MDlaMBMxETAPBgNVBAMMCEtQMSBST09UMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPn6zObnrjGPUb0ozc3MCOOcHwtQABZmUHtB1jxRXWwYXKo+iTms2wJjDS5fhz2UmUptsbdFwPdvT2t7K8cpaZBcovC3jLvEAMmjO+nU3FQrdopZ6MhBjpgIezAvJ9LUhrYctqUJzfViqtLl0dL+YRjaVdfCz5z0iZn4rv2VSf3QIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAHtS9RjMIRzeEpH9MKIaMLR7wVb55MYW7E2CVuIbsHmT+KyDBFsYbAylgc76cH1b8F53ECygS9jCpzfKtO61WVPPlUhsL13i2XbzCtj8DSPXaW5pgvpwClQZ+dpGFz8D/MYLSdjTdls8dbhJ5O08ckSKcrIGHcF90oeepVXOmiTw"); |
| static byte[] extInvVersionCA = Base64.decode( "MIICKDCCAZGgAwIBAgIGAV3ZFmI/MA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCEtQMSBST09UMB4XDTE3MDgxMzAwNTUwNFoXDTE3MDgxMzAxMjUwOVowETEPMA0GA1UEAwwGS1AxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChlaZhX9/eHmtfravHzs/E0g6ZhWTmD9aNNvuuz/GCBF9AMS6QQCGVhEzxESn0gLzs1bM/9M/EaylHS3Ecvi6QYdkrTKRDj38FDzrDhiPlM3TxY0XuUQ3Py590k8yZDcuEeVEQeoUx83qOnO7o/cL+vECfMj9ImYFFgY5sMcKkVQIDAQABo4GIMIGFMEAGA1UdIwQ5MDeAFAfTyJtmNkinVjfd7/2Giy6krDTpoRekFTATMREwDwYDVQQDDAhLUDEgUk9PVIIGAV3ZFmI+MB0GA1UdDgQWBBQkMq+wajXvKQaJtSdpvDJn77bU9zASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOBgQAqmKtykmixemAvppo2tTmekLsL93+/DMR+oz1iK2rjhqYzEF1/pM9VUyG+Ni1924U8tzGbXv2lL3MiToRSyjO50HHfnE7PfOvNiTUj73PTn27tPl03eWO3CtsOTGxtE2vpNyXyFXm4SFZlSicOXE0o/kUrNGVYvnjs/jjcNlPiHQ=="); |
| static byte[] extInvVersionEE = Base64.decode( "MIICJjCCAY+gAwIBBQIGAV3ZFmJAMA0GCSqGSIb3DQEBCwUAMBExDzANBgNVBAMMBktQMSBDQTAeFw0xNzA4MTMwMDU1MDRaFw0xNzA4MTMwMTI1MDlaMBExDzANBgNVBAMMBktQMSBFRTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6PXdCOvE33+mMcal/rC+I7zdJqcc6OBhn+Lyku29TRcYplMA5mkh7WkjLtRYBUAzHukN/GXb1Mo+dFkvCnKO/l4gLWyVuf23rL6iELt8X1KVJdJlrDElCmTgl6lA0Omq7QhNrsv5Vdk7mK2mbJzl0bj4fcu5dc23nQXEskmGrZsCAwEAAaOBiDCBhTBABgNVHSMEOTA3gBQkMq+wajXvKQaJtSdpvDJn77bU96EXpBUwEzERMA8GA1UEAwwIS1AxIFJPT1SCBgFd2RZiPzAdBgNVHQ4EFgQU3Nw/DFxNqK1fRhc/W8W4o3mkCHQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADgYEAjMTiKgLC2Kb5+elvfD/+CM8pNeLt5Y43sMSTpgIrebdWPA2hyvjvW/upsIYIquGrymOYBU/K0abQlkNUbBHpQCQMPQ6iPXuhTQj/P7rt7McLl6OXV/DQqgF+39y0xWAzoZbgMKrQaSr9oRmEVt6xzLM92JS67w8Xgbh39PGBfEg="); |
| |
| static byte[] extInvExtTrust = Base64.decode("MIIBmjCCAQMCBgFd2SFqKjANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhLUDEgUk9PVDAeFw0xNzA4MTMwMTA3MDdaFw0xNzA4MTMwMTM3MTJaMBMxETAPBgNVBAMMCEtQMSBST09UMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEY3toxiphhoeoTd79/Uznb1YyKjYgxtXkYVQLZ+Q76bJFQftVVcUHw25/A/2qgSc8XPflGRpn82Qn/B7s3fxEglgeY0ekdYjea5+jZSJj70p1QcC60yH1NKGxE0ASBuv/22IoHhdu5dOTmiWegikKUXblBD1wAxbbvOcXFs2x/wIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAJPG9wt9edpTaCc0z03xGNF/M6x5cLx5eLgZaBFt+FO3S1xWIVby+iU8Hw2mzHOc58Fghw1jEwLaslQYadx9667NedGu7dYyY318h+VhaDppQqkhJiQl5Q8aTvVNt60fDEVLjvB7E6Z+CafVGR1jNrXxLDe6zVf/BZJK7QrkTKh4"); |
| static byte[] extInvExtCA = Base64.decode("MIICKDCCAZGgAwIBAgIGAV3ZIWorMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCEtQMSBST09UMB4XDTE3MDgxMzAxMDcwN1oXDTE3MDgxMzAxMzcxMlowETEPMA0GA1UEAwwGS1AxIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJKySmanEENpLJdPwpM/v0I7H0bW9ZlIxRpiL+/Z4uvF3j0r0O42Tm+dW8Ub42DzHcQ8pK/n/k2Wb4Jf7cP8+TGTAne3bgC24USW131XUZxaunGt4tCqZ0RNWpmBQUcUM0lgntDSfcvyv3QFB+nwLc93GYij9l3FaeUcHkwFiKsQIDAQABo4GIMIGFMEAGA1UdIwQ5MDeAFLnC9UF+JqEqboFH84ab9dEAkwEBoRekFTATMREwDwYDVQQDDAhLUDEgUk9PVIIGAV3ZIWoqMB0GA1UdDgQWBBQkr/0UP1MKPGQH7bkRNctHMsVQsjASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOBgQCZxLwkAPif1H2P398MHK3NLf3mrmLsP41ZphdHnSLNROlY9PdO5I/dfhElzVXW2oxecIIKbOQsjZe0FOSGvZHEhLftQmOdfGc5QfGf5w9CSFCCBe5vHdMjglRLVhNB51jz6DB7Dp0MjFDgkQI4lBHaiMVkE+HUZjNLwBddHH58Sw=="); |
| static byte[] extInvExtEE = Base64.decode("MIICNjCCAZ+gAwIBAgIGAV3ZIWosMA0GCSqGSIb3DQEBCwUAMBExDzANBgNVBAMMBktQMSBDQTAeFw0xNzA4MTMwMTA3MDdaFw0xNzA4MTMwMTM3MTJaMBExDzANBgNVBAMMBktQMSBFRTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAj6WOoo8xHLLo+CT0l288xZDK3OsF64lPfNVkFnrRI65Ywl89M19nNF5Q24hF1FS6getO5oU+BhvRqft1/De22SME9SzKqs3G6uMxACKrMqgni1QBEOC/DdZ5Uaxh2s4lEgxbN0PQZIarAgLtAIgzRM4CrvofxFMwQy/neUuWmeMCAwEAAaOBmDCBlTBABgNVHSMEOTA3gBQkr/0UP1MKPGQH7bkRNctHMsVQsqEXpBUwEzERMA8GA1UEAwwIS1AxIFJPT1SCBgFd2SFqKzAdBgNVHQ4EFgQU/yuQXlvqXJQsbqB6whCPu5bwFCAwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4GBABYUGar9s7wlM3Qlnja7uc7U8FqU+xH4e8/Jk64ku7DdwXelEbKo/FTFAzh464aiFP4eMDOH7YThXyTruPudEAvYyWY7eaEgRqA2MmL0uWHSrN+HR9aBeqrMCJK/E2e1egvk2whJHMimhDUFJ3cIPsFhazMvLTnVgWGMjOqQtuP+"); |
| |
| private void checkInvalidCertPath() |
| throws Exception |
| { |
| checkInvalidPath(extInvTrust, extInvCA, extInvEE, "version 1 certificate contains extra data"); |
| checkInvalidPath(extInvV2Trust, extInvV2CA, extInvV2EE, "version 2 certificate cannot contain extensions"); |
| checkInvalidPath(extInvVersionTrust, extInvVersionCA, extInvVersionEE, "version number not recognised"); |
| checkInvalidPath(extInvExtTrust, extInvExtCA, extInvExtEE, "repeated extension found: 2.5.29.15"); |
| } |
| |
| private void checkInvalidPath(byte[] root, byte[] inter, byte[] ee, String expected) |
| throws Exception |
| { |
| X509Certificate rootCert = new X509CertificateObject(X509CertificateStructure.getInstance(root)); |
| X509Certificate interCert = new X509CertificateObject(X509CertificateStructure.getInstance(inter)); |
| X509Certificate finalCert = new X509CertificateObject(X509CertificateStructure.getInstance(ee)); |
| List list = new ArrayList(); |
| list.add(rootCert); |
| list.add(interCert); |
| list.add(finalCert); |
| |
| CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(list); |
| CertStore store = CertStore.getInstance("Collection", ccsp, "BC"); |
| Date validDate = new Date(rootCert.getNotBefore().getTime() + 60 * 1000); |
| //validating path |
| List certchain = new ArrayList(); |
| certchain.add(finalCert); |
| certchain.add(interCert); |
| CertPath cp = CertificateFactory.getInstance("X.509", "BC").generateCertPath(certchain); |
| Set trust = new HashSet(); |
| trust.add(new TrustAnchor(rootCert, null)); |
| |
| CertPathValidator cpv = CertPathValidator.getInstance("PKIX", "BC"); |
| PKIXParameters param = new PKIXParameters(trust); |
| param.addCertStore(store); |
| param.setDate(validDate); |
| param.setRevocationEnabled(false); |
| |
| try |
| { |
| PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult)cpv.validate(cp, param); |
| fail("valid path passed"); |
| } |
| catch (CertPathValidatorException e) |
| { |
| isTrue(e.getMessage().equals(expected)); |
| } |
| |
| // check that our cert factory also rejects - the EE is always the invalid one |
| CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); |
| |
| try |
| { |
| cf.generateCertificate(new ByteArrayInputStream(ee)); |
| } |
| catch (CertificateException e) |
| { |
| isTrue(e.getMessage().equals("parsing issue: " + expected)); |
| } |
| } |
| |
| public String getName() |
| { |
| return "CertPathValidator"; |
| } |
| |
| public static void main( |
| String[] args) |
| { |
| Security.addProvider(new BouncyCastleProvider()); |
| |
| runTest(new CertPathValidatorTest()); |
| } |
| |
| private static class MyChecker |
| extends PKIXCertPathChecker |
| { |
| private static int count; |
| |
| public void init(boolean forward) |
| throws CertPathValidatorException |
| { |
| //To change body of implemented methods use File | Settings | File Templates. |
| } |
| |
| public boolean isForwardCheckingSupported() |
| { |
| return true; |
| } |
| |
| public Set getSupportedExtensions() |
| { |
| return null; |
| } |
| |
| public void check(Certificate cert, Collection unresolvedCritExts) |
| throws CertPathValidatorException |
| { |
| count++; |
| } |
| |
| public int getCount() |
| { |
| return count; |
| } |
| } |
| |
| public static class X509CertificateObject |
| extends X509Certificate |
| { |
| static final String CERTIFICATE_POLICIES = Extension.certificatePolicies.getId(); |
| static final String POLICY_MAPPINGS = Extension.policyMappings.getId(); |
| static final String INHIBIT_ANY_POLICY = Extension.inhibitAnyPolicy.getId(); |
| static final String ISSUING_DISTRIBUTION_POINT = Extension.issuingDistributionPoint.getId(); |
| static final String FRESHEST_CRL = Extension.freshestCRL.getId(); |
| static final String DELTA_CRL_INDICATOR = Extension.deltaCRLIndicator.getId(); |
| static final String POLICY_CONSTRAINTS = Extension.policyConstraints.getId(); |
| static final String BASIC_CONSTRAINTS = Extension.basicConstraints.getId(); |
| static final String CRL_DISTRIBUTION_POINTS = Extension.cRLDistributionPoints.getId(); |
| static final String SUBJECT_ALTERNATIVE_NAME = Extension.subjectAlternativeName.getId(); |
| static final String NAME_CONSTRAINTS = Extension.nameConstraints.getId(); |
| static final String AUTHORITY_KEY_IDENTIFIER = Extension.authorityKeyIdentifier.getId(); |
| static final String KEY_USAGE = Extension.keyUsage.getId(); |
| static final String CRL_NUMBER = Extension.cRLNumber.getId(); |
| static final String ANY_POLICY = "2.5.29.32.0"; |
| |
| private org.bouncycastle.asn1.x509.X509CertificateStructure c; |
| private BasicConstraints basicConstraints; |
| private boolean[] keyUsage; |
| private boolean hashValueSet; |
| private int hashValue; |
| |
| public X509CertificateObject( |
| org.bouncycastle.asn1.x509.X509CertificateStructure c) |
| throws CertificateParsingException |
| { |
| this.c = c; |
| |
| try |
| { |
| byte[] bytes = this.getExtensionBytes("2.5.29.19"); |
| |
| if (bytes != null) |
| { |
| basicConstraints = BasicConstraints.getInstance(ASN1Primitive.fromByteArray(bytes)); |
| } |
| } |
| catch (Exception e) |
| { |
| throw new CertificateParsingException("cannot construct BasicConstraints: " + e); |
| } |
| |
| try |
| { |
| byte[] bytes = this.getExtensionBytes("2.5.29.15"); |
| if (bytes != null) |
| { |
| ASN1BitString bits = DERBitString.getInstance(ASN1Primitive.fromByteArray(bytes)); |
| |
| bytes = bits.getBytes(); |
| int length = (bytes.length * 8) - bits.getPadBits(); |
| |
| keyUsage = new boolean[(length < 9) ? 9 : length]; |
| |
| for (int i = 0; i != length; i++) |
| { |
| keyUsage[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; |
| } |
| } |
| else |
| { |
| keyUsage = null; |
| } |
| } |
| catch (Exception e) |
| { |
| throw new CertificateParsingException("cannot construct KeyUsage: " + e); |
| } |
| } |
| |
| public void checkValidity() |
| throws CertificateExpiredException, CertificateNotYetValidException |
| { |
| this.checkValidity(new Date()); |
| } |
| |
| public void checkValidity( |
| Date date) |
| throws CertificateExpiredException, CertificateNotYetValidException |
| { |
| if (date.getTime() > this.getNotAfter().getTime()) // for other VM compatibility |
| { |
| throw new CertificateExpiredException("certificate expired on " + c.getEndDate().getTime()); |
| } |
| |
| if (date.getTime() < this.getNotBefore().getTime()) |
| { |
| throw new CertificateNotYetValidException("certificate not valid till " + c.getStartDate().getTime()); |
| } |
| } |
| |
| public int getVersion() |
| { |
| return c.getVersion(); |
| } |
| |
| public BigInteger getSerialNumber() |
| { |
| return c.getSerialNumber().getValue(); |
| } |
| |
| public Principal getIssuerDN() |
| { |
| try |
| { |
| return new X509Principal(X500Name.getInstance(c.getIssuer().getEncoded())); |
| } |
| catch (IOException e) |
| { |
| return null; |
| } |
| } |
| |
| public X500Principal getIssuerX500Principal() |
| { |
| try |
| { |
| ByteArrayOutputStream bOut = new ByteArrayOutputStream(); |
| ASN1OutputStream aOut = new ASN1OutputStream(bOut); |
| |
| aOut.writeObject(c.getIssuer()); |
| |
| return new X500Principal(bOut.toByteArray()); |
| } |
| catch (IOException e) |
| { |
| throw new IllegalStateException("can't encode issuer DN"); |
| } |
| } |
| |
| public Principal getSubjectDN() |
| { |
| return new X509Principal(X500Name.getInstance(c.getSubject().toASN1Primitive())); |
| } |
| |
| public X500Principal getSubjectX500Principal() |
| { |
| try |
| { |
| ByteArrayOutputStream bOut = new ByteArrayOutputStream(); |
| ASN1OutputStream aOut = new ASN1OutputStream(bOut); |
| |
| aOut.writeObject(c.getSubject()); |
| |
| return new X500Principal(bOut.toByteArray()); |
| } |
| catch (IOException e) |
| { |
| throw new IllegalStateException("can't encode issuer DN"); |
| } |
| } |
| |
| public Date getNotBefore() |
| { |
| return c.getStartDate().getDate(); |
| } |
| |
| public Date getNotAfter() |
| { |
| return c.getEndDate().getDate(); |
| } |
| |
| public byte[] getTBSCertificate() |
| throws CertificateEncodingException |
| { |
| try |
| { |
| return c.getTBSCertificate().getEncoded(ASN1Encoding.DER); |
| } |
| catch (IOException e) |
| { |
| throw new CertificateEncodingException(e.toString()); |
| } |
| } |
| |
| public byte[] getSignature() |
| { |
| return c.getSignature().getOctets(); |
| } |
| |
| /** |
| * return a more "meaningful" representation for the signature algorithm used in |
| * the certficate. |
| */ |
| public String getSigAlgName() |
| { |
| Provider prov = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME); |
| |
| if (prov != null) |
| { |
| String algName = prov.getProperty("Alg.Alias.Signature." + this.getSigAlgOID()); |
| |
| if (algName != null) |
| { |
| return algName; |
| } |
| } |
| |
| Provider[] provs = Security.getProviders(); |
| |
| // |
| // search every provider looking for a real algorithm |
| // |
| for (int i = 0; i != provs.length; i++) |
| { |
| String algName = provs[i].getProperty("Alg.Alias.Signature." + this.getSigAlgOID()); |
| if (algName != null) |
| { |
| return algName; |
| } |
| } |
| |
| return this.getSigAlgOID(); |
| } |
| |
| /** |
| * return the object identifier for the signature. |
| */ |
| public String getSigAlgOID() |
| { |
| return c.getSignatureAlgorithm().getAlgorithm().getId(); |
| } |
| |
| /** |
| * return the signature parameters, or null if there aren't any. |
| */ |
| public byte[] getSigAlgParams() |
| { |
| if (c.getSignatureAlgorithm().getParameters() != null) |
| { |
| try |
| { |
| return c.getSignatureAlgorithm().getParameters().toASN1Primitive().getEncoded(ASN1Encoding.DER); |
| } |
| catch (IOException e) |
| { |
| return null; |
| } |
| } |
| else |
| { |
| return null; |
| } |
| } |
| |
| public boolean[] getIssuerUniqueID() |
| { |
| DERBitString id = c.getTBSCertificate().getIssuerUniqueId(); |
| |
| if (id != null) |
| { |
| byte[] bytes = id.getBytes(); |
| boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()]; |
| |
| for (int i = 0; i != boolId.length; i++) |
| { |
| boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; |
| } |
| |
| return boolId; |
| } |
| |
| return null; |
| } |
| |
| public boolean[] getSubjectUniqueID() |
| { |
| DERBitString id = c.getTBSCertificate().getSubjectUniqueId(); |
| |
| if (id != null) |
| { |
| byte[] bytes = id.getBytes(); |
| boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()]; |
| |
| for (int i = 0; i != boolId.length; i++) |
| { |
| boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; |
| } |
| |
| return boolId; |
| } |
| |
| return null; |
| } |
| |
| public boolean[] getKeyUsage() |
| { |
| return keyUsage; |
| } |
| |
| public List getExtendedKeyUsage() |
| throws CertificateParsingException |
| { |
| byte[] bytes = this.getExtensionBytes("2.5.29.37"); |
| |
| if (bytes != null) |
| { |
| try |
| { |
| ASN1InputStream dIn = new ASN1InputStream(bytes); |
| ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); |
| List list = new ArrayList(); |
| |
| for (int i = 0; i != seq.size(); i++) |
| { |
| list.add(((ASN1ObjectIdentifier)seq.getObjectAt(i)).getId()); |
| } |
| |
| return Collections.unmodifiableList(list); |
| } |
| catch (Exception e) |
| { |
| throw new CertificateParsingException("error processing extended key usage extension"); |
| } |
| } |
| |
| return null; |
| } |
| |
| public int getBasicConstraints() |
| { |
| if (basicConstraints != null) |
| { |
| if (basicConstraints.isCA()) |
| { |
| if (basicConstraints.getPathLenConstraint() == null) |
| { |
| return Integer.MAX_VALUE; |
| } |
| else |
| { |
| return basicConstraints.getPathLenConstraint().intValue(); |
| } |
| } |
| else |
| { |
| return -1; |
| } |
| } |
| |
| return -1; |
| } |
| |
| public Collection getSubjectAlternativeNames() |
| throws CertificateParsingException |
| { |
| return getAlternativeNames(getExtensionBytes(Extension.subjectAlternativeName.getId())); |
| } |
| |
| public Collection getIssuerAlternativeNames() |
| throws CertificateParsingException |
| { |
| return getAlternativeNames(getExtensionBytes(Extension.issuerAlternativeName.getId())); |
| } |
| |
| public Set getCriticalExtensionOIDs() |
| { |
| if (this.getVersion() == 3) |
| { |
| Set set = new HashSet(); |
| X509Extensions extensions = c.getTBSCertificate().getExtensions(); |
| |
| if (extensions != null) |
| { |
| Enumeration e = extensions.oids(); |
| |
| while (e.hasMoreElements()) |
| { |
| ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); |
| X509Extension ext = extensions.getExtension(oid); |
| |
| if (ext.isCritical()) |
| { |
| set.add(oid.getId()); |
| } |
| } |
| |
| return set; |
| } |
| } |
| |
| return null; |
| } |
| |
| private byte[] getExtensionBytes(String oid) |
| { |
| X509Extensions exts = c.getTBSCertificate().getExtensions(); |
| |
| if (exts != null) |
| { |
| X509Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid)); |
| if (ext != null) |
| { |
| return ext.getValue().getOctets(); |
| } |
| } |
| |
| return null; |
| } |
| |
| public byte[] getExtensionValue(String oid) |
| { |
| X509Extensions exts = c.getTBSCertificate().getExtensions(); |
| |
| if (exts != null) |
| { |
| X509Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid)); |
| |
| if (ext != null) |
| { |
| try |
| { |
| return ext.getValue().getEncoded(); |
| } |
| catch (Exception e) |
| { |
| throw new IllegalStateException("error parsing " + e.toString()); |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| public Set getNonCriticalExtensionOIDs() |
| { |
| if (this.getVersion() == 3) |
| { |
| Set set = new HashSet(); |
| X509Extensions extensions = c.getTBSCertificate().getExtensions(); |
| |
| if (extensions != null) |
| { |
| Enumeration e = extensions.oids(); |
| |
| while (e.hasMoreElements()) |
| { |
| ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); |
| X509Extension ext = extensions.getExtension(oid); |
| |
| if (!ext.isCritical()) |
| { |
| set.add(oid.getId()); |
| } |
| } |
| |
| return set; |
| } |
| } |
| |
| return null; |
| } |
| |
| public boolean hasUnsupportedCriticalExtension() |
| { |
| if (this.getVersion() == 3) |
| { |
| X509Extensions extensions = c.getTBSCertificate().getExtensions(); |
| |
| if (extensions != null) |
| { |
| Enumeration e = extensions.oids(); |
| |
| while (e.hasMoreElements()) |
| { |
| ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); |
| String oidId = oid.getId(); |
| |
| if (oidId.equals(KEY_USAGE) |
| || oidId.equals(CERTIFICATE_POLICIES) |
| || oidId.equals(POLICY_MAPPINGS) |
| || oidId.equals(INHIBIT_ANY_POLICY) |
| || oidId.equals(CRL_DISTRIBUTION_POINTS) |
| || oidId.equals(ISSUING_DISTRIBUTION_POINT) |
| || oidId.equals(DELTA_CRL_INDICATOR) |
| || oidId.equals(POLICY_CONSTRAINTS) |
| || oidId.equals(BASIC_CONSTRAINTS) |
| || oidId.equals(SUBJECT_ALTERNATIVE_NAME) |
| || oidId.equals(NAME_CONSTRAINTS)) |
| { |
| continue; |
| } |
| |
| X509Extension ext = extensions.getExtension(oid); |
| |
| if (ext.isCritical()) |
| { |
| return true; |
| } |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| public PublicKey getPublicKey() |
| { |
| try |
| { |
| return BouncyCastleProvider.getPublicKey(c.getSubjectPublicKeyInfo()); |
| } |
| catch (IOException e) |
| { |
| return null; // should never happen... |
| } |
| } |
| |
| public byte[] getEncoded() |
| throws CertificateEncodingException |
| { |
| try |
| { |
| return c.getEncoded(ASN1Encoding.DER); |
| } |
| catch (IOException e) |
| { |
| throw new CertificateEncodingException(e.toString()); |
| } |
| } |
| |
| public boolean equals( |
| Object o) |
| { |
| if (o == this) |
| { |
| return true; |
| } |
| |
| if (!(o instanceof Certificate)) |
| { |
| return false; |
| } |
| |
| Certificate other = (Certificate)o; |
| |
| try |
| { |
| byte[] b1 = this.getEncoded(); |
| byte[] b2 = other.getEncoded(); |
| |
| return Arrays.areEqual(b1, b2); |
| } |
| catch (CertificateEncodingException e) |
| { |
| return false; |
| } |
| } |
| |
| public synchronized int hashCode() |
| { |
| if (!hashValueSet) |
| { |
| hashValue = calculateHashCode(); |
| hashValueSet = true; |
| } |
| |
| return hashValue; |
| } |
| |
| private int calculateHashCode() |
| { |
| try |
| { |
| int hashCode = 0; |
| byte[] certData = this.getEncoded(); |
| for (int i = 1; i < certData.length; i++) |
| { |
| hashCode += certData[i] * i; |
| } |
| return hashCode; |
| } |
| catch (CertificateEncodingException e) |
| { |
| return 0; |
| } |
| } |
| |
| public String toString() |
| { |
| StringBuffer buf = new StringBuffer(); |
| String nl = Strings.lineSeparator(); |
| |
| buf.append(" [0] Version: ").append(this.getVersion()).append(nl); |
| buf.append(" SerialNumber: ").append(this.getSerialNumber()).append(nl); |
| buf.append(" IssuerDN: ").append(this.getIssuerDN()).append(nl); |
| buf.append(" Start Date: ").append(this.getNotBefore()).append(nl); |
| buf.append(" Final Date: ").append(this.getNotAfter()).append(nl); |
| buf.append(" SubjectDN: ").append(this.getSubjectDN()).append(nl); |
| buf.append(" Public Key: ").append(this.getPublicKey()).append(nl); |
| buf.append(" Signature Algorithm: ").append(this.getSigAlgName()).append(nl); |
| |
| byte[] sig = this.getSignature(); |
| |
| buf.append(" Signature: ").append(new String(Hex.encode(sig, 0, 20))).append(nl); |
| for (int i = 20; i < sig.length; i += 20) |
| { |
| if (i < sig.length - 20) |
| { |
| buf.append(" ").append(new String(Hex.encode(sig, i, 20))).append(nl); |
| } |
| else |
| { |
| buf.append(" ").append(new String(Hex.encode(sig, i, sig.length - i))).append(nl); |
| } |
| } |
| |
| X509Extensions extensions = c.getTBSCertificate().getExtensions(); |
| |
| if (extensions != null) |
| { |
| Enumeration e = extensions.oids(); |
| |
| if (e.hasMoreElements()) |
| { |
| buf.append(" Extensions: \n"); |
| } |
| |
| while (e.hasMoreElements()) |
| { |
| ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); |
| X509Extension ext = extensions.getExtension(oid); |
| |
| if (ext.getValue() != null) |
| { |
| byte[] octs = ext.getValue().getOctets(); |
| ASN1InputStream dIn = new ASN1InputStream(octs); |
| buf.append(" critical(").append(ext.isCritical()).append(") "); |
| try |
| { |
| if (oid.equals(Extension.basicConstraints)) |
| { |
| buf.append(BasicConstraints.getInstance(dIn.readObject())).append(nl); |
| } |
| else if (oid.equals(Extension.keyUsage)) |
| { |
| buf.append(KeyUsage.getInstance(dIn.readObject())).append(nl); |
| } |
| else if (oid.equals(MiscObjectIdentifiers.netscapeCertType)) |
| { |
| buf.append(new NetscapeCertType((DERBitString)dIn.readObject())).append(nl); |
| } |
| else if (oid.equals(MiscObjectIdentifiers.netscapeRevocationURL)) |
| { |
| buf.append(new NetscapeRevocationURL((DERIA5String)dIn.readObject())).append(nl); |
| } |
| else if (oid.equals(MiscObjectIdentifiers.verisignCzagExtension)) |
| { |
| buf.append(new VerisignCzagExtension((DERIA5String)dIn.readObject())).append(nl); |
| } |
| else |
| { |
| buf.append(oid.getId()); |
| buf.append(" value = ").append(ASN1Dump.dumpAsString(dIn.readObject())).append(nl); |
| //buf.append(" value = ").append("*****").append(nl); |
| } |
| } |
| catch (Exception ex) |
| { |
| buf.append(oid.getId()); |
| // buf.append(" value = ").append(new String(Hex.encode(ext.getExtnValue().getOctets()))).append(nl); |
| buf.append(" value = ").append("*****").append(nl); |
| } |
| } |
| else |
| { |
| buf.append(nl); |
| } |
| } |
| } |
| |
| return buf.toString(); |
| } |
| |
| public final void verify( |
| PublicKey key) |
| throws CertificateException, NoSuchAlgorithmException, |
| InvalidKeyException, NoSuchProviderException, SignatureException |
| { |
| Signature signature; |
| String sigName = "SHA256withRSA"; |
| |
| try |
| { |
| signature = Signature.getInstance(sigName, BouncyCastleProvider.PROVIDER_NAME); |
| } |
| catch (Exception e) |
| { |
| signature = Signature.getInstance(sigName); |
| } |
| |
| checkSignature(key, signature); |
| } |
| |
| public final void verify( |
| PublicKey key, |
| String sigProvider) |
| throws CertificateException, NoSuchAlgorithmException, |
| InvalidKeyException, NoSuchProviderException, SignatureException |
| { |
| String sigName = "SHA256withRSA"; |
| Signature signature; |
| |
| if (sigProvider != null) |
| { |
| signature = Signature.getInstance(sigName, sigProvider); |
| } |
| else |
| { |
| signature = Signature.getInstance(sigName); |
| } |
| |
| checkSignature(key, signature); |
| } |
| |
| public final void verify( |
| PublicKey key, |
| Provider sigProvider) |
| throws CertificateException, NoSuchAlgorithmException, |
| InvalidKeyException, SignatureException |
| { |
| String sigName = "SHA256withRSA"; |
| Signature signature; |
| |
| if (sigProvider != null) |
| { |
| signature = Signature.getInstance(sigName, sigProvider); |
| } |
| else |
| { |
| signature = Signature.getInstance(sigName); |
| } |
| |
| checkSignature(key, signature); |
| } |
| |
| private void checkSignature( |
| PublicKey key, |
| Signature signature) |
| throws CertificateException, NoSuchAlgorithmException, |
| SignatureException, InvalidKeyException |
| { |
| if (!isAlgIdEqual(c.getSignatureAlgorithm(), c.getTBSCertificate().getSignature())) |
| { |
| throw new CertificateException("signature algorithm in TBS cert not same as outer cert"); |
| } |
| |
| ASN1Encodable params = c.getSignatureAlgorithm().getParameters(); |
| |
| signature.initVerify(key); |
| |
| signature.update(this.getTBSCertificate()); |
| |
| if (!signature.verify(this.getSignature())) |
| { |
| throw new SignatureException("certificate does not verify with supplied key"); |
| } |
| } |
| |
| private boolean isAlgIdEqual(AlgorithmIdentifier id1, AlgorithmIdentifier id2) |
| { |
| if (!id1.getAlgorithm().equals(id2.getAlgorithm())) |
| { |
| return false; |
| } |
| |
| if (id1.getParameters() == null) |
| { |
| if (id2.getParameters() != null && !id2.getParameters().equals(DERNull.INSTANCE)) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| if (id2.getParameters() == null) |
| { |
| if (id1.getParameters() != null && !id1.getParameters().equals(DERNull.INSTANCE)) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| return id1.getParameters().equals(id2.getParameters()); |
| } |
| |
| private static Collection getAlternativeNames(byte[] extVal) |
| throws CertificateParsingException |
| { |
| if (extVal == null) |
| { |
| return null; |
| } |
| try |
| { |
| Collection temp = new ArrayList(); |
| Enumeration it = ASN1Sequence.getInstance(extVal).getObjects(); |
| while (it.hasMoreElements()) |
| { |
| GeneralName genName = GeneralName.getInstance(it.nextElement()); |
| List list = new ArrayList(); |
| list.add(Integers.valueOf(genName.getTagNo())); |
| switch (genName.getTagNo()) |
| { |
| case GeneralName.ediPartyName: |
| case GeneralName.x400Address: |
| case GeneralName.otherName: |
| list.add(genName.getEncoded()); |
| break; |
| case GeneralName.directoryName: |
| list.add(X500Name.getInstance(RFC4519Style.INSTANCE, genName.getName()).toString()); |
| break; |
| case GeneralName.dNSName: |
| case GeneralName.rfc822Name: |
| case GeneralName.uniformResourceIdentifier: |
| list.add(((ASN1String)genName.getName()).getString()); |
| break; |
| case GeneralName.registeredID: |
| list.add(ASN1ObjectIdentifier.getInstance(genName.getName()).getId()); |
| break; |
| case GeneralName.iPAddress: |
| byte[] addrBytes = DEROctetString.getInstance(genName.getName()).getOctets(); |
| final String addr; |
| try |
| { |
| addr = InetAddress.getByAddress(addrBytes).getHostAddress(); |
| } |
| catch (UnknownHostException e) |
| { |
| continue; |
| } |
| list.add(addr); |
| break; |
| default: |
| throw new IOException("Bad tag number: " + genName.getTagNo()); |
| } |
| |
| temp.add(Collections.unmodifiableList(list)); |
| } |
| if (temp.size() == 0) |
| { |
| return null; |
| } |
| return Collections.unmodifiableCollection(temp); |
| } |
| catch (Exception e) |
| { |
| throw new CertificateParsingException(e.getMessage()); |
| } |
| } |
| } |
| } |
| |