Path: blob/master/test/jdk/java/security/cert/X509CertSelectorTest.java
41149 views
/*1* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22import static sun.security.x509.GeneralNameInterface.NAME_DIRECTORY;23import static sun.security.x509.NameConstraintsExtension.EXCLUDED_SUBTREES;24import static sun.security.x509.NameConstraintsExtension.PERMITTED_SUBTREES;2526import java.io.ByteArrayInputStream;27import java.io.ByteArrayOutputStream;28import java.io.IOException;29import java.io.InputStream;30import java.math.BigInteger;31import java.security.GeneralSecurityException;32import java.security.KeyFactory;33import java.security.PublicKey;34import java.security.cert.CertificateException;35import java.security.cert.CertificateFactory;36import java.security.cert.X509CertSelector;37import java.security.cert.X509Certificate;38import java.security.spec.X509EncodedKeySpec;39import java.util.Base64;40import java.util.Calendar;41import java.util.Date;42import java.util.HashSet;43import java.util.Iterator;44import java.util.List;45import java.util.Set;4647import sun.security.util.DerInputStream;48import sun.security.util.DerOutputStream;49import sun.security.util.DerValue;50import sun.security.util.ObjectIdentifier;51import sun.security.x509.AlgorithmId;52import sun.security.x509.AuthorityKeyIdentifierExtension;53import sun.security.x509.CertificatePoliciesExtension;54import sun.security.x509.DNSName;55import sun.security.x509.GeneralName;56import sun.security.x509.GeneralNameInterface;57import sun.security.x509.GeneralNames;58import sun.security.x509.GeneralSubtree;59import sun.security.x509.GeneralSubtrees;60import sun.security.x509.KeyIdentifier;61import sun.security.x509.NameConstraintsExtension;62import sun.security.x509.PolicyInformation;63import sun.security.x509.PrivateKeyUsageExtension;64import sun.security.x509.SubjectAlternativeNameExtension;65import sun.security.x509.X500Name;6667/*68* @test69* @bug 807493170* @summary This class tests the X509CertSelector. The tests check particular criteria71* by setting them to a value that should match our test certificate and72* ensuring that they do match, then setting them to a value that should not73* match our test certificate and ensuring that they do not match.74* @modules java.base/sun.security.x50975* java.base/sun.security.util76*/77public class X509CertSelectorTest {78/*79Certificate:80Data:81Version: 3 (0x2)82Serial Number: 954172088 (0x38df82b8)83Signature Algorithm: dsaWithSHA184Issuer: C=us, O=sun, OU=testing85Validity86Not Before: Mar 27 15:48:08 2000 GMT87Not After : Jun 25 14:48:08 2000 GMT88Subject: C=us, O=sun, OU=testing, CN=mullan89Subject Public Key Info:90Public Key Algorithm: dsaEncryption91pub: 092P: 093Q: 094G: 095X509v3 extensions:96X509v3 Name Constraints: critical970D.B0@.>1.0...U....us1.098..U.99..sun1.0...U....testing1.0100..U....mullan101X509v3 Subject Key Identifier:10256:E8:88:AE:9D:B5:3F:2B:CB:A0:4C:4B:E2:87:53:07:33:77:1B:DF103X509v3 Authority Key Identifier:104keyid:8E:DD:AF:6F:EE:02:12:F4:61:E9:2F:E3:64:1A:6F:71:32:25:20:C0105106X509v3 Subject Alternative Name:107email:[email protected]108X509v3 Private Key Usage Period:109Not Before: Jan 1 05:00:00 2000 GMT, Not After: Jan 1 05:00:00 2001 GMT110X509v3 Key Usage: critical111Digital Signature112X509v3 Certificate Policies:1130$0\..*...0.0...+.......0..114Testing...115Signature Algorithm: dsaWithSHA1116r:11744:c7:35:40:5d:6c:28:75:7f:73:b2:f8:0d:72:6c:11809:65:b8:81:14119s:12076:79:f5:c7:37:3b:0d:9b:db:70:2f:20:80:36:e3:12180:e8:a6:c6:71122*/123private static final String testCert =124"-----BEGIN CERTIFICATE-----\n" +125"MIICLjCCAeygAwIBAgIEON+CuDALBgcqhkjOOAQDBQAwLTELMAkGA1UEBhMCdXMx\n" +126"DDAKBgNVBAoTA3N1bjEQMA4GA1UECxMHdGVzdGluZzAeFw0wMDAzMjcxNTQ4MDha\n" +127"Fw0wMDA2MjUxNDQ4MDhaMD4xCzAJBgNVBAYTAnVzMQwwCgYDVQQKEwNzdW4xEDAO\n" +128"BgNVBAsTB3Rlc3RpbmcxDzANBgNVBAMTBm11bGxhbjAcMBQGByqGSM44BAEwCQIB\n" +129"AAIBAAIBAAMEAAIBAKOCASMwggEfMFAGA1UdHgEB/wRGMESgQjBApD4xCzAJBgNV\n" +130"BAYTAnVzMQwwCgYDVQQKEwNzdW4xEDAOBgNVBAsTB3Rlc3RpbmcxDzANBgNVBAMT\n" +131"Bm11bGxhbjAdBgNVHQ4EFgQUVuiIrp21PyvLoExL4odTBzN3G98wHwYDVR0jBBgw\n" +132"FoAUjt2vb+4CEvRh6S/jZBpvcTIlIMAwHgYDVR0RBBcwFYETbXVsbGFuQGVhc3Qu\n" +133"c3VuLmNvbTArBgNVHRAEJDAigA8yMDAwMDEwMTA1MDAwMFqBDzIwMDEwMTAxMDUw\n" +134"MDAwWjAPBgNVHQ8BAf8EBQMDB4AAMC0GA1UdIAQmMCQwIgYEKoSAADAaMBgGCCsG\n" +135"AQUFBwICMAwSClRlc3RpbmcuLi4wCwYHKoZIzjgEAwUAAy8AMCwCFETHNUBdbCh1\n" +136"f3Oy+A1ybAlluIEUAhR2efXHNzsNm9twLyCANuOA6KbGcQ==\n" +137"-----END CERTIFICATE-----\n" +138"";139140private static final String testKey =141"MIIBtjCCASsGByqGSM44BAEwggEeAoGBAIVWPEkcxbxhQRCqVzg55tNqbP5j0K4kdu4bkmXvfqC5\n" +142"+qA75DvnfzsOJseb+9AuKXWk/DvCzFDmrY1YaU3scZC3OQEO9lEO3F4VDKOaudY6OT1SI22pAIwz\n" +143"j5pvq+i7zOp4xUqkQUeh/4iQSfxOT5UrFGjkcbnbpVkCXD/GxAz7AhUAjtnm3dVIddUUHl6wxpZ7\n" +144"GcA6gSsCgYAf/PXzQtemgIDjpFrNNSgTEKkLposBXKatAM+gUKlMUjf8SQvquqPxDtRrscGjXkoL\n" +145"oTkaR7/akULYFpBvUcFkeIFiCnJg8M9XhCWdLvn9MPt+jR2oxookvCb9xLtD6WvIM/wd/nZ1iK4u\n" +146"iY1+q85xvns/Awbtwl7oZDAwE2TUKAOBhAACgYBDc9UZ+3xsZubUZvRG5cpyJceYpJp2exOPVJXn\n" +147"jR4CcR+cT9bAJpFSxqE/8KtNHXxHdu4f3DU67IMOVDpugzihyzXJvNm3w2H9x+6xczHG2wjvAJeh\n" +148"X62EWbUatxPXFAoVKZWuUbaYaZzdWBDtNRrCuKKsLo0GFy8g2BZISuD3jw==\n" +149"";150151// Certificate to run tests on152private final X509Certificate cert;153154public static void main(String[] args) throws Exception {155X509CertSelectorTest test = new X509CertSelectorTest();156test.doTest();157}158159public X509CertSelectorTest() throws CertificateException, IOException {160cert = (X509Certificate) CertificateFactory.getInstance("X.509")161.generateCertificate(new ByteArrayInputStream(testCert.getBytes()));162}163164// Runs the test.165private void doTest() throws Exception {166System.out.println("START OF TESTS FOR " + "X509CertSelector");167168testSerialNumber();169testIssuer();170testSubjectKeyIdentifier();171testAuthorityKeyIdentifier();172testCertificateValid();173testPrivateKeyValid();174testSubjectPublicKeyAlgID();175testKeyUsage();176testSubjectAltName();177testPolicy();178testPathToName();179testSubject();180testSubjectPublicKey();181testNameConstraints();182testBasicConstraints();183testCertificate();184}185186// Tests matching on the serial number contained in the certificate.187private void testSerialNumber() {188System.out.println("X.509 Certificate Match on serialNumber");189// bad match190X509CertSelector selector = new X509CertSelector();191selector.setSerialNumber(new BigInteger("999999999"));192checkMatch(selector, cert, false);193194// good match195selector.setSerialNumber(cert.getSerialNumber());196checkMatch(selector, cert, true);197}198199// Tests matching on the issuer name contained in the certificate.200private void testIssuer() throws IOException {201System.out.println("X.509 Certificate Match on issuer");202// bad match203X509CertSelector selector = new X509CertSelector();204selector.setIssuer("ou=bogus,ou=east,o=sun,c=us");205checkMatch(selector, cert, false);206207// good match208selector.setIssuer((cert.getIssuerX500Principal()).getName("RFC2253"));209checkMatch(selector, cert, true);210}211212/*213* Tests matching on the subject key identifier contained in the214* certificate.215*/216private void testSubjectKeyIdentifier() throws IOException {217System.out.println("X.509 Certificate Match on subjectKeyIdentifier");218// bad match219X509CertSelector selector = new X509CertSelector();220byte[] b = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };221selector.setSubjectKeyIdentifier(b);222checkMatch(selector, cert, false);223224// good match225DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.14"));226byte[] encoded = in.getOctetString();227selector.setSubjectKeyIdentifier(encoded);228checkMatch(selector, cert, true);229}230231/*232* Tests matching on the authority key identifier contained in the233* certificate.234*/235private void testAuthorityKeyIdentifier() throws IOException {236System.out.println("X.509 Certificate Match on authorityKeyIdentifier");237// bad match238X509CertSelector selector = new X509CertSelector();239byte[] b = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };240AuthorityKeyIdentifierExtension a = new AuthorityKeyIdentifierExtension(new KeyIdentifier(b), null, null);241selector.setAuthorityKeyIdentifier(a.getExtensionValue());242checkMatch(selector, cert, false);243244// good match245DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.35"));246byte[] encoded = in.getOctetString();247selector.setAuthorityKeyIdentifier(encoded);248checkMatch(selector, cert, true);249}250251/*252* Tests matching on the certificate validity component contained in the253* certificate.254*/255private void testCertificateValid() {256System.out.println("X.509 Certificate Match on certificateValid");257// bad match258X509CertSelector selector = new X509CertSelector();259Calendar cal = Calendar.getInstance();260cal.set(1968, 12, 31);261selector.setCertificateValid(cal.getTime());262checkMatch(selector, cert, false);263264// good match265selector.setCertificateValid(cert.getNotBefore());266checkMatch(selector, cert, true);267}268269/*270* Tests matching on the private key validity component contained in the271* certificate.272*/273private void testPrivateKeyValid() throws IOException, CertificateException {274System.out.println("X.509 Certificate Match on privateKeyValid");275// bad match276X509CertSelector selector = new X509CertSelector();277Calendar cal = Calendar.getInstance();278cal.set(1968, 12, 31);279selector.setPrivateKeyValid(cal.getTime());280checkMatch(selector, cert, false);281282// good match283DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.16"));284byte[] encoded = in.getOctetString();285PrivateKeyUsageExtension ext = new PrivateKeyUsageExtension(false, encoded);286Date validDate = (Date) ext.get(PrivateKeyUsageExtension.NOT_BEFORE);287selector.setPrivateKeyValid(validDate);288checkMatch(selector, cert, true);289290}291292private ObjectIdentifier getCertPubKeyAlgOID(X509Certificate xcert) throws IOException {293byte[] encodedKey = xcert.getPublicKey().getEncoded();294DerValue val = new DerValue(encodedKey);295if (val.tag != DerValue.tag_Sequence) {296throw new RuntimeException("invalid key format");297}298299return AlgorithmId.parse(val.data.getDerValue()).getOID();300}301302/*303* Tests matching on the subject public key algorithm ID component contained304* in the certificate.305*/306private void testSubjectPublicKeyAlgID() throws IOException {307System.out.println("X.509 Certificate Match on subjectPublicKeyAlgID");308// bad match309X509CertSelector selector = new X509CertSelector();310selector.setSubjectPublicKeyAlgID("2.5.29.14");311checkMatch(selector, cert, false);312313// good match314selector.setSubjectPublicKeyAlgID(getCertPubKeyAlgOID(cert).toString());315checkMatch(selector, cert, true);316317}318319// Tests matching on the key usage extension contained in the certificate.320private void testKeyUsage() {321System.out.println("X.509 Certificate Match on keyUsage");322// bad match323X509CertSelector selector = new X509CertSelector();324boolean[] keyUsage = { true, false, true, false, true, false, true, false };325selector.setKeyUsage(keyUsage);326System.out.println("Selector = " + selector.toString());327checkMatch(selector, cert, false);328329// good match330selector.setKeyUsage(cert.getKeyUsage());331System.out.println("Selector = " + selector.toString());332checkMatch(selector, cert, true);333}334335/*336* Tests matching on the subject alternative name extension contained in the337* certificate.338*/339private void testSubjectAltName() throws IOException {340System.out.println("X.509 Certificate Match on subjectAltName");341// bad match342X509CertSelector selector = new X509CertSelector();343GeneralNameInterface dnsName = new DNSName("foo.com");344DerOutputStream tmp = new DerOutputStream();345dnsName.encode(tmp);346selector.addSubjectAlternativeName(2, tmp.toByteArray());347checkMatch(selector, cert, false);348349// good match350DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.17"));351byte[] encoded = in.getOctetString();352SubjectAlternativeNameExtension ext = new SubjectAlternativeNameExtension(false, encoded);353GeneralNames names = (GeneralNames) ext.get(SubjectAlternativeNameExtension.SUBJECT_NAME);354GeneralName name = (GeneralName) names.get(0);355selector.setSubjectAlternativeNames(null);356DerOutputStream tmp2 = new DerOutputStream();357name.getName().encode(tmp2);358selector.addSubjectAlternativeName(name.getType(), tmp2.toByteArray());359checkMatch(selector, cert, true);360361// good match 2 (matches at least one)362selector.setMatchAllSubjectAltNames(false);363selector.addSubjectAlternativeName(2, "foo.com");364checkMatch(selector, cert, true);365}366367/*368* Tests matching on the policy constraints extension contained in the369* certificate.370*/371private void testPolicy() throws IOException {372System.out.println("X.509 Certificate Match on certificatePolicies");373// test encoding of CertificatePoliciesExtension because we wrote the374// code375// bad match376X509CertSelector selector = new X509CertSelector();377Set<String> s = new HashSet<>();378s.add(new String("1.2.5.7.68"));379selector.setPolicy(s);380checkMatch(selector, cert, false);381382// good match383DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.32"));384CertificatePoliciesExtension ext = new CertificatePoliciesExtension(false, in.getOctetString());385List<PolicyInformation> policies = ext.get(CertificatePoliciesExtension.POLICIES);386// match on the first policy id387PolicyInformation policyInfo = (PolicyInformation) policies.get(0);388s.clear();389s.add(policyInfo.getPolicyIdentifier().getIdentifier().toString());390selector.setPolicy(s);391checkMatch(selector, cert, true);392}393394/*395* Tests matching on the name constraints extension contained in the396* certificate.397*/398private void testPathToName() throws IOException {399System.out.println("X.509 Certificate Match on pathToName");400401X509CertSelector selector = null;402DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.30"));403byte[] encoded = in.getOctetString();404NameConstraintsExtension ext = new NameConstraintsExtension(false, encoded);405GeneralSubtrees permitted = (GeneralSubtrees) ext.get(PERMITTED_SUBTREES);406GeneralSubtrees excluded = (GeneralSubtrees) ext.get(EXCLUDED_SUBTREES);407408// bad matches on pathToName within excluded subtrees409if (excluded != null) {410Iterator<GeneralSubtree> e = excluded.iterator();411while (e.hasNext()) {412GeneralSubtree tree = e.next();413if (tree.getName().getType() == NAME_DIRECTORY) {414X500Name excludedDN1 = new X500Name(tree.getName().toString());415X500Name excludedDN2 = new X500Name("CN=Bogus, " + tree.getName().toString());416DerOutputStream derDN1 = new DerOutputStream();417DerOutputStream derDN2 = new DerOutputStream();418excludedDN1.encode(derDN1);419excludedDN2.encode(derDN2);420selector = new X509CertSelector();421selector.addPathToName(NAME_DIRECTORY, derDN1.toByteArray());422checkMatch(selector, cert, false);423selector.setPathToNames(null);424selector.addPathToName(NAME_DIRECTORY, derDN2.toByteArray());425checkMatch(selector, cert, false);426}427}428}429430// good matches on pathToName within permitted subtrees431if (permitted != null) {432Iterator<GeneralSubtree> e = permitted.iterator();433while (e.hasNext()) {434GeneralSubtree tree = e.next();435if (tree.getName().getType() == NAME_DIRECTORY) {436X500Name permittedDN1 = new X500Name(tree.getName().toString());437X500Name permittedDN2 = new X500Name("CN=good, " + tree.getName().toString());438DerOutputStream derDN1 = new DerOutputStream();439DerOutputStream derDN2 = new DerOutputStream();440permittedDN1.encode(derDN1);441permittedDN2.encode(derDN2);442selector = new X509CertSelector();443selector.addPathToName(NAME_DIRECTORY, derDN1.toByteArray());444checkMatch(selector, cert, true);445selector.setPathToNames(null);446selector.addPathToName(NAME_DIRECTORY, derDN2.toByteArray());447checkMatch(selector, cert, true);448}449}450}451}452453// Tests matching on the subject name contained in the certificate.454private void testSubject() throws IOException {455System.out.println("X.509 Certificate Match on subject");456// bad match457X509CertSelector selector = new X509CertSelector();458selector.setSubject("ou=bogus,ou=east,o=sun,c=us");459checkMatch(selector, cert, false);460461// good match462selector.setSubject(cert.getSubjectX500Principal().getName("RFC2253"));463checkMatch(selector, cert, true);464}465466// Tests matching on the subject public key contained in the certificate.467private void testSubjectPublicKey() throws IOException, GeneralSecurityException {468System.out.println("X.509 Certificate Match on subject public key");469// bad match470X509CertSelector selector = new X509CertSelector();471X509EncodedKeySpec keySpec = new X509EncodedKeySpec(472Base64.getMimeDecoder().decode(testKey.getBytes()));473KeyFactory keyFactory = KeyFactory.getInstance("DSA");474PublicKey pubKey = keyFactory.generatePublic(keySpec);475selector.setSubjectPublicKey(pubKey);476checkMatch(selector, cert, false);477478// good match479selector.setSubjectPublicKey(cert.getPublicKey());480checkMatch(selector, cert, true);481}482483// Tests matching on the name constraints contained in the certificate.484private void testNameConstraints() throws IOException {485System.out.println("X.509 Certificate Match on name constraints");486// bad match487GeneralSubtrees subjectTree = new GeneralSubtrees();488subjectTree.add(getGeneralSubtree((X500Name) cert.getSubjectDN()));489NameConstraintsExtension ext = new NameConstraintsExtension((GeneralSubtrees) null, subjectTree);490X509CertSelector selector = new X509CertSelector();491selector.setNameConstraints(ext.getExtensionValue());492checkMatch(selector, cert, false);493494// good match495ext = new NameConstraintsExtension(subjectTree, null);496selector.setNameConstraints(ext.getExtensionValue());497checkMatch(selector, cert, true);498}499500// Tests matching on basic constraints.501private void testBasicConstraints() {502System.out.println("X.509 Certificate Match on basic constraints");503// bad match504X509CertSelector selector = new X509CertSelector();505int mpl = cert.getBasicConstraints();506selector.setBasicConstraints(0);507checkMatch(selector, cert, false);508509// good match510selector.setBasicConstraints(mpl);511checkMatch(selector, cert, true);512}513514// Tests certificateEquals criterion515private void testCertificate() {516System.out.println("X.509 Certificate Match on certificateEquals criterion");517518X509CertSelector selector = new X509CertSelector();519// good match520selector.setCertificate(cert);521checkMatch(selector, cert, true);522}523524private void checkMatch(X509CertSelector selector, X509Certificate cert, boolean match) {525boolean result = selector.match(cert);526if (match != result)527throw new RuntimeException(selector + " match " + cert + " is " + result + ", but expect " + match);528}529530private static GeneralSubtree getGeneralSubtree(GeneralNameInterface gni) {531// Create a new GeneralSubtree with the specified name, 0 base, and532// unlimited length533GeneralName gn = new GeneralName(gni);534GeneralSubtree subTree = new GeneralSubtree(gn, 0, -1);535return subTree;536}537}538539540