# HG changeset patch # User fyuan # Date 1442310192 -10800 # Node ID afc55db01c8e5933de2ed9a0898f463ab5645b31 # Parent 64827b676968f320eda6f83fa7e6205344145a73 8074931: Additional tests for CertPath API Reviewed-by: mullan diff -r 64827b676968 -r afc55db01c8e test/java/security/cert/CertPathEncodingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/security/cert/CertPathEncodingTest.java Tue Sep 15 12:43:12 2015 +0300 @@ -0,0 +1,253 @@ +/* + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.io.ByteArrayInputStream; +import java.security.cert.CertPath; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; + +/* + * @test + * @bug 8074931 + * @summary CertPathEncodingTest tests the ability of the CertPath and + * CertificateFactory to encode and decode CertPaths. + */ +public final class CertPathEncodingTest { + /* + Certificate: + Data: + Version: 3 (0x2) + Serial Number: 935438132 (0x37c1a734) + Signature Algorithm: dsaWithSHA1 + Issuer: C=us, O=sun, OU=east, OU=bcn, CN=yassir + Validity + Not Before: Aug 23 19:55:32 1999 GMT + Not After : Aug 22 19:55:32 2000 GMT + Subject: C=us, O=sun, OU=east, OU=bcn + Subject Public Key Info: + Public Key Algorithm: dsaEncryption + pub: + 63:47:4f:f6:29:e5:98:a2:21:fd:da:97:9e:3f:ca: + b0:17:49:8d:8a:a7:06:0d:a6:78:97:39:59:33:72: + a2:a5:74:d5:3a:ef:e6:7c:07:d7:8e:8e:d1:66:73: + 99:14:04:96:f5:31:d6:72:ee:d2:53:f8:90:b5:f3: + c3:f1:64:ba:1a:9e:c0:0a:da:92:48:c5:d3:84:7e: + 48:09:66:d9:51:ba:74:56:5a:77:8a:8c:9a:9c:f6: + 84:12:61:12:51:dc:c6:4f:84:94:ec:cb:78:51:83: + 8c:20:8a:53:7b:d2:b6:36:df:50:35:95:1f:cb:50: + 55:8b:3f:fb:e2:77:cb + P: + 00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec: + e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6: + 51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf: + c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34: + 6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b: + 10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7: + c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35: + 54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef: + f2:22:03:19:9d:d1:48:01:c7 + Q: + 00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb: + 84:0b:f0:58:1c:f5 + G: + 00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8: + 57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d: + 07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10: + 81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09: + 32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3: + ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62: + f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89: + a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55: + 25:64:01:4c:3b:fe:cf:49:2a + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Certificate Sign + Signature Algorithm: dsaWithSHA1 + r: + 52:80:52:2b:2c:3d:02:66:58:b4:dc:ef:52:26:70: + 1b:53:ca:b3:7d + s: + 62:03:b2:ab:3e:18:2a:66:09:b6:ce:d4:05:a5:8e: + a5:7a:0d:55:67 + */ + private static final String cert1 = + "-----BEGIN CERTIFICATE-----\n" + + "MIICzTCCAougAwIBAgIEN8GnNDALBgcqhkjOOAQDBQAwSTELMAkGA1UEBhMCdXMx\n" + + "DDAKBgNVBAoTA3N1bjENMAsGA1UECxMEZWFzdDEMMAoGA1UECxMDYmNuMQ8wDQYD\n" + + "VQQDEwZ5YXNzaXIwHhcNOTkwODIzMTk1NTMyWhcNMDAwODIyMTk1NTMyWjA4MQsw\n" + + "CQYDVQQGEwJ1czEMMAoGA1UEChMDc3VuMQ0wCwYDVQQLEwRlYXN0MQwwCgYDVQQL\n" + + "EwNiY24wggG1MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qcLuzk5/YR\n" + + "t1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZ\n" + + "UKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOu\n" + + "K2HXKu/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKBgQD34aCF1ps9\n" + + "3su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgW\n" + + "E7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQ\n" + + "iaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBggACf2NHT/Yp5ZiiIf3al54/yrAX\n" + + "SY2KpwYNpniXOVkzcqKldNU67+Z8B9eOjtFmc5kUBJb1MdZy7tJT+JC188PxZLoa\n" + + "nsAK2pJIxdOEfkgJZtlRunRWWneKjJqc9oQSYRJR3MZPhJTsy3hRg4wgilN70rY2\n" + + "31A1lR/LUFWLP/vid8ujEzARMA8GA1UdDwEB/wQFAwMHpAAwCwYHKoZIzjgEAwUA\n" + + "Ay8AMCwCFFKAUissPQJmWLTc71ImcBtTyrN9AhRiA7KrPhgqZgm2ztQFpY6leg1V\n" + + "Zw==\n" + + "-----END CERTIFICATE-----\n" + + ""; + + /* + Certificate: + Data: + Version: 3 (0x2) + Serial Number: 935095671 (0x37bc6d77) + Signature Algorithm: dsaWithSHA1 + Issuer: C=us, O=sun, OU=east, OU=bcn, CN=yassir + Validity + Not Before: Aug 19 20:47:51 1999 GMT + Not After : Aug 18 20:47:51 2000 GMT + Subject: C=us, O=sun, OU=east, OU=bcn, CN=yassir + Subject Public Key Info: + Public Key Algorithm: dsaEncryption + pub: + 0a:cc:a4:ec:d6:88:45:c2:24:6b:0d:78:f1:82:f3: + 5e:3e:31:5d:fb:64:d5:06:5e:39:16:f1:0a:85:d1: + ff:d1:a4:74:c5:e6:b0:ba:93:1c:ee:69:51:be:3b: + a6:66:44:50:b4:f0:5e:0e:dd:9f:08:71:fe:a1:91: + 2e:d4:9e:6b:b2:c0:82:3c:91:6c:18:b0:d9:bc:a3: + 48:91:3f:8b:59:01:61:00:02:ab:22:31:bc:7c:6c: + 0d:9f:ed:be:33:e6:5c:44:9e:62:30:95:f8:6d:22: + d7:e5:85:4c:b0:98:6e:ad:cc:ca:3b:ad:cb:fa:f7: + 9f:37:13:f7:ca:e2:22:ba + P: + 00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec: + e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6: + 51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf: + c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34: + 6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b: + 10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7: + c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35: + 54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef: + f2:22:03:19:9d:d1:48:01:c7 + Q: + 00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb: + 84:0b:f0:58:1c:f5 + G: + 00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8: + 57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d: + 07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10: + 81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09: + 32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3: + ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62: + f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89: + a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55: + 25:64:01:4c:3b:fe:cf:49:2a + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Certificate Sign + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:5 + Signature Algorithm: dsaWithSHA1 + r: + 2f:88:46:37:94:92:b2:02:07:5b:8d:76:e5:81:23: + 85:7f:bc:8d:b9 + s: + 00:8b:d7:41:fa:11:c7:ab:27:92:5d:0a:03:98:56: + 36:42:5f:f5:1f:9d + */ + private static final String cert2 = + "-----BEGIN CERTIFICATE-----\n" + + "MIIC9TCCArKgAwIBAgIEN7xtdzALBgcqhkjOOAQDBQAwSTELMAkGA1UEBhMCdXMx\n" + + "DDAKBgNVBAoTA3N1bjENMAsGA1UECxMEZWFzdDEMMAoGA1UECxMDYmNuMQ8wDQYD\n" + + "VQQDEwZ5YXNzaXIwHhcNOTkwODE5MjA0NzUxWhcNMDAwODE4MjA0NzUxWjBJMQsw\n" + + "CQYDVQQGEwJ1czEMMAoGA1UEChMDc3VuMQ0wCwYDVQQLEwRlYXN0MQwwCgYDVQQL\n" + + "EwNiY24xDzANBgNVBAMTBnlhc3NpcjCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9\n" + + "f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2\n" + + "y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD\n" + + "9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLr\n" + + "hAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrU\n" + + "WU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6\n" + + "ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GEAAKB\n" + + "gArMpOzWiEXCJGsNePGC814+MV37ZNUGXjkW8QqF0f/RpHTF5rC6kxzuaVG+O6Zm\n" + + "RFC08F4O3Z8Icf6hkS7UnmuywII8kWwYsNm8o0iRP4tZAWEAAqsiMbx8bA2f7b4z\n" + + "5lxEnmIwlfhtItflhUywmG6tzMo7rcv69583E/fK4iK6oycwJTAPBgNVHQ8BAf8E\n" + + "BQMDB6QAMBIGA1UdEwEB/wQIMAYBAf8CAQUwCwYHKoZIzjgEAwUAAzAAMC0CFC+I\n" + + "RjeUkrICB1uNduWBI4V/vI25AhUAi9dB+hHHqyeSXQoDmFY2Ql/1H50=\n" + + "-----END CERTIFICATE-----\n" + + ""; + + private static final String pkcs7path = + "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\n" + + ""; + + // Runs test of CertPath encoding and decoding. + public static void main(String[] args) throws Exception { + // Make the CertPath whose encoded form has already been stored + CertificateFactory certFac = CertificateFactory.getInstance("X509"); + + final List certs = new ArrayList<>(); + certs.add(certFac.generateCertificate(new ByteArrayInputStream(cert1.getBytes()))); + certs.add(certFac.generateCertificate(new ByteArrayInputStream(cert2.getBytes()))); + + CertPath cp = certFac.generateCertPath(certs); + + // Get the encoded form of the CertPath we made + byte[] encoded = cp.getEncoded("PKCS7"); + + // check if it matches the encoded value + if (!Arrays.equals(encoded, Base64.getMimeDecoder().decode(pkcs7path.getBytes()))) { + throw new RuntimeException("PKCS#7 encoding doesn't match stored value"); + } + + // Generate a CertPath from the encoded value and check if it equals + // the CertPath generated from the certificates + CertPath decodedCP = certFac.generateCertPath(new ByteArrayInputStream(encoded), "PKCS7"); + if (!decodedCP.equals(cp)) { + throw new RuntimeException("CertPath decoded from PKCS#7 isn't equal to original"); + } + } +} diff -r 64827b676968 -r afc55db01c8e test/java/security/cert/X509CertSelectorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/security/cert/X509CertSelectorTest.java Tue Sep 15 12:43:12 2015 +0300 @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import static sun.security.x509.GeneralNameInterface.NAME_DIRECTORY; +import static sun.security.x509.NameConstraintsExtension.EXCLUDED_SUBTREES; +import static sun.security.x509.NameConstraintsExtension.PERMITTED_SUBTREES; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509CertSelector; +import java.security.cert.X509Certificate; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; +import java.util.Calendar; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import sun.security.util.DerInputStream; +import sun.security.util.DerOutputStream; +import sun.security.util.DerValue; +import sun.security.util.ObjectIdentifier; +import sun.security.x509.AlgorithmId; +import sun.security.x509.AuthorityKeyIdentifierExtension; +import sun.security.x509.CertificatePoliciesExtension; +import sun.security.x509.DNSName; +import sun.security.x509.GeneralName; +import sun.security.x509.GeneralNameInterface; +import sun.security.x509.GeneralNames; +import sun.security.x509.GeneralSubtree; +import sun.security.x509.GeneralSubtrees; +import sun.security.x509.KeyIdentifier; +import sun.security.x509.NameConstraintsExtension; +import sun.security.x509.PolicyInformation; +import sun.security.x509.PrivateKeyUsageExtension; +import sun.security.x509.SubjectAlternativeNameExtension; +import sun.security.x509.X500Name; + +/* + * @test + * @bug 8074931 + * @summary This class tests the X509CertSelector. The tests check particular criteria + * by setting them to a value that should match our test certificate and + * ensuring that they do match, then setting them to a value that should not + * match our test certificate and ensuring that they do not match. + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + */ +public class X509CertSelectorTest { + /* + Certificate: + Data: + Version: 3 (0x2) + Serial Number: 954172088 (0x38df82b8) + Signature Algorithm: dsaWithSHA1 + Issuer: C=us, O=sun, OU=testing + Validity + Not Before: Mar 27 15:48:08 2000 GMT + Not After : Jun 25 14:48:08 2000 GMT + Subject: C=us, O=sun, OU=testing, CN=mullan + Subject Public Key Info: + Public Key Algorithm: dsaEncryption + pub: 0 + P: 0 + Q: 0 + G: 0 + X509v3 extensions: + X509v3 Name Constraints: critical + 0D.B0@.>1.0...U....us1.0 + ..U. + ..sun1.0...U....testing1.0 + ..U....mullan + X509v3 Subject Key Identifier: + 56:E8:88:AE:9D:B5:3F:2B:CB:A0:4C:4B:E2:87:53:07:33:77:1B:DF + X509v3 Authority Key Identifier: + keyid:8E:DD:AF:6F:EE:02:12:F4:61:E9:2F:E3:64:1A:6F:71:32:25:20:C0 + + X509v3 Subject Alternative Name: + email:mullan@east.sun.com + X509v3 Private Key Usage Period: + Not Before: Jan 1 05:00:00 2000 GMT, Not After: Jan 1 05:00:00 2001 GMT + X509v3 Key Usage: critical + Digital Signature + X509v3 Certificate Policies: + 0$0\..*...0.0...+.......0.. + Testing... + Signature Algorithm: dsaWithSHA1 + r: + 44:c7:35:40:5d:6c:28:75:7f:73:b2:f8:0d:72:6c: + 09:65:b8:81:14 + s: + 76:79:f5:c7:37:3b:0d:9b:db:70:2f:20:80:36:e3: + 80:e8:a6:c6:71 + */ + private static final String testCert = + "-----BEGIN CERTIFICATE-----\n" + + "MIICLjCCAeygAwIBAgIEON+CuDALBgcqhkjOOAQDBQAwLTELMAkGA1UEBhMCdXMx\n" + + "DDAKBgNVBAoTA3N1bjEQMA4GA1UECxMHdGVzdGluZzAeFw0wMDAzMjcxNTQ4MDha\n" + + "Fw0wMDA2MjUxNDQ4MDhaMD4xCzAJBgNVBAYTAnVzMQwwCgYDVQQKEwNzdW4xEDAO\n" + + "BgNVBAsTB3Rlc3RpbmcxDzANBgNVBAMTBm11bGxhbjAcMBQGByqGSM44BAEwCQIB\n" + + "AAIBAAIBAAMEAAIBAKOCASMwggEfMFAGA1UdHgEB/wRGMESgQjBApD4xCzAJBgNV\n" + + "BAYTAnVzMQwwCgYDVQQKEwNzdW4xEDAOBgNVBAsTB3Rlc3RpbmcxDzANBgNVBAMT\n" + + "Bm11bGxhbjAdBgNVHQ4EFgQUVuiIrp21PyvLoExL4odTBzN3G98wHwYDVR0jBBgw\n" + + "FoAUjt2vb+4CEvRh6S/jZBpvcTIlIMAwHgYDVR0RBBcwFYETbXVsbGFuQGVhc3Qu\n" + + "c3VuLmNvbTArBgNVHRAEJDAigA8yMDAwMDEwMTA1MDAwMFqBDzIwMDEwMTAxMDUw\n" + + "MDAwWjAPBgNVHQ8BAf8EBQMDB4AAMC0GA1UdIAQmMCQwIgYEKoSAADAaMBgGCCsG\n" + + "AQUFBwICMAwSClRlc3RpbmcuLi4wCwYHKoZIzjgEAwUAAy8AMCwCFETHNUBdbCh1\n" + + "f3Oy+A1ybAlluIEUAhR2efXHNzsNm9twLyCANuOA6KbGcQ==\n" + + "-----END CERTIFICATE-----\n" + + ""; + + private static final String testKey = + "MIIBtjCCASsGByqGSM44BAEwggEeAoGBAIVWPEkcxbxhQRCqVzg55tNqbP5j0K4kdu4bkmXvfqC5\n" + + "+qA75DvnfzsOJseb+9AuKXWk/DvCzFDmrY1YaU3scZC3OQEO9lEO3F4VDKOaudY6OT1SI22pAIwz\n" + + "j5pvq+i7zOp4xUqkQUeh/4iQSfxOT5UrFGjkcbnbpVkCXD/GxAz7AhUAjtnm3dVIddUUHl6wxpZ7\n" + + "GcA6gSsCgYAf/PXzQtemgIDjpFrNNSgTEKkLposBXKatAM+gUKlMUjf8SQvquqPxDtRrscGjXkoL\n" + + "oTkaR7/akULYFpBvUcFkeIFiCnJg8M9XhCWdLvn9MPt+jR2oxookvCb9xLtD6WvIM/wd/nZ1iK4u\n" + + "iY1+q85xvns/Awbtwl7oZDAwE2TUKAOBhAACgYBDc9UZ+3xsZubUZvRG5cpyJceYpJp2exOPVJXn\n" + + "jR4CcR+cT9bAJpFSxqE/8KtNHXxHdu4f3DU67IMOVDpugzihyzXJvNm3w2H9x+6xczHG2wjvAJeh\n" + + "X62EWbUatxPXFAoVKZWuUbaYaZzdWBDtNRrCuKKsLo0GFy8g2BZISuD3jw==\n" + + ""; + + // Certificate to run tests on + private final X509Certificate cert; + + public static void main(String[] args) throws Exception { + X509CertSelectorTest test = new X509CertSelectorTest(); + test.doTest(); + } + + public X509CertSelectorTest() throws CertificateException, IOException { + cert = (X509Certificate) CertificateFactory.getInstance("X.509") + .generateCertificate(new ByteArrayInputStream(testCert.getBytes())); + } + + // Runs the test. + private void doTest() throws Exception { + System.out.println("START OF TESTS FOR " + "X509CertSelector"); + + testSerialNumber(); + testIssuer(); + testSubjectKeyIdentifier(); + testAuthorityKeyIdentifier(); + testCertificateValid(); + testPrivateKeyValid(); + testSubjectPublicKeyAlgID(); + testKeyUsage(); + testSubjectAltName(); + testPolicy(); + testPathToName(); + testSubject(); + testSubjectPublicKey(); + testNameConstraints(); + testBasicConstraints(); + testCertificate(); + } + + // Tests matching on the serial number contained in the certificate. + private void testSerialNumber() { + System.out.println("X.509 Certificate Match on serialNumber"); + // bad match + X509CertSelector selector = new X509CertSelector(); + selector.setSerialNumber(new BigInteger("999999999")); + checkMatch(selector, cert, false); + + // good match + selector.setSerialNumber(cert.getSerialNumber()); + checkMatch(selector, cert, true); + } + + // Tests matching on the issuer name contained in the certificate. + private void testIssuer() throws IOException { + System.out.println("X.509 Certificate Match on issuer"); + // bad match + X509CertSelector selector = new X509CertSelector(); + selector.setIssuer("ou=bogus,ou=east,o=sun,c=us"); + checkMatch(selector, cert, false); + + // good match + selector.setIssuer((cert.getIssuerX500Principal()).getName("RFC2253")); + checkMatch(selector, cert, true); + } + + /* + * Tests matching on the subject key identifier contained in the + * certificate. + */ + private void testSubjectKeyIdentifier() throws IOException { + System.out.println("X.509 Certificate Match on subjectKeyIdentifier"); + // bad match + X509CertSelector selector = new X509CertSelector(); + byte[] b = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + selector.setSubjectKeyIdentifier(b); + checkMatch(selector, cert, false); + + // good match + DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.14")); + byte[] encoded = in.getOctetString(); + selector.setSubjectKeyIdentifier(encoded); + checkMatch(selector, cert, true); + } + + /* + * Tests matching on the authority key identifier contained in the + * certificate. + */ + private void testAuthorityKeyIdentifier() throws IOException { + System.out.println("X.509 Certificate Match on authorityKeyIdentifier"); + // bad match + X509CertSelector selector = new X509CertSelector(); + byte[] b = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + AuthorityKeyIdentifierExtension a = new AuthorityKeyIdentifierExtension(new KeyIdentifier(b), null, null); + selector.setAuthorityKeyIdentifier(a.getExtensionValue()); + checkMatch(selector, cert, false); + + // good match + DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.35")); + byte[] encoded = in.getOctetString(); + selector.setAuthorityKeyIdentifier(encoded); + checkMatch(selector, cert, true); + } + + /* + * Tests matching on the certificate validity component contained in the + * certificate. + */ + private void testCertificateValid() { + System.out.println("X.509 Certificate Match on certificateValid"); + // bad match + X509CertSelector selector = new X509CertSelector(); + Calendar cal = Calendar.getInstance(); + cal.set(1968, 12, 31); + selector.setCertificateValid(cal.getTime()); + checkMatch(selector, cert, false); + + // good match + selector.setCertificateValid(cert.getNotBefore()); + checkMatch(selector, cert, true); + } + + /* + * Tests matching on the private key validity component contained in the + * certificate. + */ + private void testPrivateKeyValid() throws IOException, CertificateException { + System.out.println("X.509 Certificate Match on privateKeyValid"); + // bad match + X509CertSelector selector = new X509CertSelector(); + Calendar cal = Calendar.getInstance(); + cal.set(1968, 12, 31); + selector.setPrivateKeyValid(cal.getTime()); + checkMatch(selector, cert, false); + + // good match + DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.16")); + byte[] encoded = in.getOctetString(); + PrivateKeyUsageExtension ext = new PrivateKeyUsageExtension(false, encoded); + Date validDate = (Date) ext.get(PrivateKeyUsageExtension.NOT_BEFORE); + selector.setPrivateKeyValid(validDate); + checkMatch(selector, cert, true); + + } + + private ObjectIdentifier getCertPubKeyAlgOID(X509Certificate xcert) throws IOException { + byte[] encodedKey = xcert.getPublicKey().getEncoded(); + DerValue val = new DerValue(encodedKey); + if (val.tag != DerValue.tag_Sequence) { + throw new RuntimeException("invalid key format"); + } + + return AlgorithmId.parse(val.data.getDerValue()).getOID(); + } + + /* + * Tests matching on the subject public key algorithm ID component contained + * in the certificate. + */ + private void testSubjectPublicKeyAlgID() throws IOException { + System.out.println("X.509 Certificate Match on subjectPublicKeyAlgID"); + // bad match + X509CertSelector selector = new X509CertSelector(); + selector.setSubjectPublicKeyAlgID("2.5.29.14"); + checkMatch(selector, cert, false); + + // good match + selector.setSubjectPublicKeyAlgID(getCertPubKeyAlgOID(cert).toString()); + checkMatch(selector, cert, true); + + } + + // Tests matching on the key usage extension contained in the certificate. + private void testKeyUsage() { + System.out.println("X.509 Certificate Match on keyUsage"); + // bad match + X509CertSelector selector = new X509CertSelector(); + boolean[] keyUsage = { true, false, true, false, true, false, true, false }; + selector.setKeyUsage(keyUsage); + System.out.println("Selector = " + selector.toString()); + checkMatch(selector, cert, false); + + // good match + selector.setKeyUsage(cert.getKeyUsage()); + System.out.println("Selector = " + selector.toString()); + checkMatch(selector, cert, true); + } + + /* + * Tests matching on the subject alternative name extension contained in the + * certificate. + */ + private void testSubjectAltName() throws IOException { + System.out.println("X.509 Certificate Match on subjectAltName"); + // bad match + X509CertSelector selector = new X509CertSelector(); + GeneralNameInterface dnsName = new DNSName("foo.com"); + DerOutputStream tmp = new DerOutputStream(); + dnsName.encode(tmp); + selector.addSubjectAlternativeName(2, tmp.toByteArray()); + checkMatch(selector, cert, false); + + // good match + DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.17")); + byte[] encoded = in.getOctetString(); + SubjectAlternativeNameExtension ext = new SubjectAlternativeNameExtension(false, encoded); + GeneralNames names = (GeneralNames) ext.get(SubjectAlternativeNameExtension.SUBJECT_NAME); + GeneralName name = (GeneralName) names.get(0); + selector.setSubjectAlternativeNames(null); + DerOutputStream tmp2 = new DerOutputStream(); + name.getName().encode(tmp2); + selector.addSubjectAlternativeName(name.getType(), tmp2.toByteArray()); + checkMatch(selector, cert, true); + + // good match 2 (matches at least one) + selector.setMatchAllSubjectAltNames(false); + selector.addSubjectAlternativeName(2, "foo.com"); + checkMatch(selector, cert, true); + } + + /* + * Tests matching on the policy constraints extension contained in the + * certificate. + */ + private void testPolicy() throws IOException { + System.out.println("X.509 Certificate Match on certificatePolicies"); + // test encoding of CertificatePoliciesExtension because we wrote the + // code + // bad match + X509CertSelector selector = new X509CertSelector(); + Set s = new HashSet<>(); + s.add(new String("1.2.5.7.68")); + selector.setPolicy(s); + checkMatch(selector, cert, false); + + // good match + DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.32")); + CertificatePoliciesExtension ext = new CertificatePoliciesExtension(false, in.getOctetString()); + List policies = ext.get(CertificatePoliciesExtension.POLICIES); + // match on the first policy id + PolicyInformation policyInfo = (PolicyInformation) policies.get(0); + s.clear(); + s.add(policyInfo.getPolicyIdentifier().getIdentifier().toString()); + selector.setPolicy(s); + checkMatch(selector, cert, true); + } + + /* + * Tests matching on the name constraints extension contained in the + * certificate. + */ + private void testPathToName() throws IOException { + System.out.println("X.509 Certificate Match on pathToName"); + + X509CertSelector selector = null; + DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.30")); + byte[] encoded = in.getOctetString(); + NameConstraintsExtension ext = new NameConstraintsExtension(false, encoded); + GeneralSubtrees permitted = (GeneralSubtrees) ext.get(PERMITTED_SUBTREES); + GeneralSubtrees excluded = (GeneralSubtrees) ext.get(EXCLUDED_SUBTREES); + + // bad matches on pathToName within excluded subtrees + if (excluded != null) { + Iterator e = excluded.iterator(); + while (e.hasNext()) { + GeneralSubtree tree = e.next(); + if (tree.getName().getType() == NAME_DIRECTORY) { + X500Name excludedDN1 = new X500Name(tree.getName().toString()); + X500Name excludedDN2 = new X500Name("CN=Bogus, " + tree.getName().toString()); + DerOutputStream derDN1 = new DerOutputStream(); + DerOutputStream derDN2 = new DerOutputStream(); + excludedDN1.encode(derDN1); + excludedDN2.encode(derDN2); + selector = new X509CertSelector(); + selector.addPathToName(NAME_DIRECTORY, derDN1.toByteArray()); + checkMatch(selector, cert, false); + selector.setPathToNames(null); + selector.addPathToName(NAME_DIRECTORY, derDN2.toByteArray()); + checkMatch(selector, cert, false); + } + } + } + + // good matches on pathToName within permitted subtrees + if (permitted != null) { + Iterator e = permitted.iterator(); + while (e.hasNext()) { + GeneralSubtree tree = e.next(); + if (tree.getName().getType() == NAME_DIRECTORY) { + X500Name permittedDN1 = new X500Name(tree.getName().toString()); + X500Name permittedDN2 = new X500Name("CN=good, " + tree.getName().toString()); + DerOutputStream derDN1 = new DerOutputStream(); + DerOutputStream derDN2 = new DerOutputStream(); + permittedDN1.encode(derDN1); + permittedDN2.encode(derDN2); + selector = new X509CertSelector(); + selector.addPathToName(NAME_DIRECTORY, derDN1.toByteArray()); + checkMatch(selector, cert, true); + selector.setPathToNames(null); + selector.addPathToName(NAME_DIRECTORY, derDN2.toByteArray()); + checkMatch(selector, cert, true); + } + } + } + } + + // Tests matching on the subject name contained in the certificate. + private void testSubject() throws IOException { + System.out.println("X.509 Certificate Match on subject"); + // bad match + X509CertSelector selector = new X509CertSelector(); + selector.setSubject("ou=bogus,ou=east,o=sun,c=us"); + checkMatch(selector, cert, false); + + // good match + selector.setSubject(cert.getSubjectX500Principal().getName("RFC2253")); + checkMatch(selector, cert, true); + } + + // Tests matching on the subject public key contained in the certificate. + private void testSubjectPublicKey() throws IOException, GeneralSecurityException { + System.out.println("X.509 Certificate Match on subject public key"); + // bad match + X509CertSelector selector = new X509CertSelector(); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec( + Base64.getMimeDecoder().decode(testKey.getBytes())); + KeyFactory keyFactory = KeyFactory.getInstance("DSA"); + PublicKey pubKey = keyFactory.generatePublic(keySpec); + selector.setSubjectPublicKey(pubKey); + checkMatch(selector, cert, false); + + // good match + selector.setSubjectPublicKey(cert.getPublicKey()); + checkMatch(selector, cert, true); + } + + // Tests matching on the name constraints contained in the certificate. + private void testNameConstraints() throws IOException { + System.out.println("X.509 Certificate Match on name constraints"); + // bad match + GeneralSubtrees subjectTree = new GeneralSubtrees(); + subjectTree.add(getGeneralSubtree((X500Name) cert.getSubjectDN())); + NameConstraintsExtension ext = new NameConstraintsExtension((GeneralSubtrees) null, subjectTree); + X509CertSelector selector = new X509CertSelector(); + selector.setNameConstraints(ext.getExtensionValue()); + checkMatch(selector, cert, false); + + // good match + ext = new NameConstraintsExtension(subjectTree, null); + selector.setNameConstraints(ext.getExtensionValue()); + checkMatch(selector, cert, true); + } + + // Tests matching on basic constraints. + private void testBasicConstraints() { + System.out.println("X.509 Certificate Match on basic constraints"); + // bad match + X509CertSelector selector = new X509CertSelector(); + int mpl = cert.getBasicConstraints(); + selector.setBasicConstraints(0); + checkMatch(selector, cert, false); + + // good match + selector.setBasicConstraints(mpl); + checkMatch(selector, cert, true); + } + + // Tests certificateEquals criterion + private void testCertificate() { + System.out.println("X.509 Certificate Match on certificateEquals criterion"); + + X509CertSelector selector = new X509CertSelector(); + // good match + selector.setCertificate(cert); + checkMatch(selector, cert, true); + } + + private void checkMatch(X509CertSelector selector, X509Certificate cert, boolean match) { + boolean result = selector.match(cert); + if (match != result) + throw new RuntimeException(selector + " match " + cert + " is " + result + ", but expect " + match); + } + + private static GeneralSubtree getGeneralSubtree(GeneralNameInterface gni) { + // Create a new GeneralSubtree with the specified name, 0 base, and + // unlimited length + GeneralName gn = new GeneralName(gni); + GeneralSubtree subTree = new GeneralSubtree(gn, 0, -1); + return subTree; + } +}