Path: blob/master/test/jdk/sun/security/provider/certpath/ResponderId/ResponderIdTests.java
41154 views
/*1* Copyright (c) 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*/2223/*24* @test25* @bug 804632126* @summary OCSP Stapling for TLS (ResponderId tests)27* @modules java.base/sun.security.provider.certpath28* java.base/sun.security.x50929*/3031import java.io.*;32import java.security.cert.*;33import java.security.KeyPair;34import java.security.KeyPairGenerator;35import java.util.AbstractMap;36import java.util.Arrays;37import java.util.Map;38import java.util.List;39import java.util.ArrayList;40import javax.security.auth.x500.X500Principal;41import sun.security.x509.KeyIdentifier;42import sun.security.provider.certpath.ResponderId;4344/*45* NOTE: this test uses Sun private classes which are subject to change.46*/47public class ResponderIdTests {4849private static final boolean debug = true;5051// Source certificate created with the following command:52// keytool -genkeypair -alias test1 -keyalg rsa -keysize 2048 \53// -validity 7300 -keystore test1.jks \54// -dname "CN=SelfSignedResponder, OU=Validation Services, O=FakeCompany"55private static final String RESP_CERT_1 =56"-----BEGIN CERTIFICATE-----\n" +57"MIIDQzCCAiugAwIBAgIEXTqCCjANBgkqhkiG9w0BAQsFADBSMRQwEgYDVQQKEwtG\n" +58"YWtlQ29tcGFueTEcMBoGA1UECxMTVmFsaWRhdGlvbiBTZXJ2aWNlczEcMBoGA1UE\n" +59"AxMTU2VsZlNpZ25lZFJlc3BvbmRlcjAeFw0xNDA4MTcwNDM2MzBaFw0zNDA4MTIw\n" +60"NDM2MzBaMFIxFDASBgNVBAoTC0Zha2VDb21wYW55MRwwGgYDVQQLExNWYWxpZGF0\n" +61"aW9uIFNlcnZpY2VzMRwwGgYDVQQDExNTZWxmU2lnbmVkUmVzcG9uZGVyMIIBIjAN\n" +62"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApt2Cmw2k9tviLxaxE8aWNuoosWKL\n" +63"h+K4mNcDGKSoiChsqRqeJEnOxijDZqyFwfkaXvpAduFqYjz+Lij2HumvAjHDTui6\n" +64"bGcbsndRDPjvVo1S7f1oWsg7oiA8Lzmjl452S7UNBsDX5Dt1e84Xxwi40B1J2y8D\n" +65"FRPfYRWRlC1Z4kzqkBBa7JhANS+W8KDstFZxL4AwWH/byNwB5dl2j04ohg/Ar54e\n" +66"mu08PIH3hmi0pAu5wn9ariA7UA5lFWRJzvgGXV5J+QVEFuvKmeJ/Q6tU5OBJGw98\n" +67"zjd7F5B0iE+rJHTNF1aGaQfIorz04onV2WjH2VZA18AaMwqlY2br1SBdTQIDAQAB\n" +68"oyEwHzAdBgNVHQ4EFgQUG09HasSTYaTIh/CxxV/rcJV1LvowDQYJKoZIhvcNAQEL\n" +69"BQADggEBAIcUomNpZxGkocIzzybLyeyC6vLF1k0/unuPAHZLDP3o2JTstPhLHOCg\n" +70"FYw1VG2i23pjwKK2x/o80tJAOmW6vowbAPnNmtNIYO3gB/ZGiKeORoGKBCRDNvFa\n" +71"6ZrWxwTzT3EpVwRe7ameES0uP8+S4q2P5LhwMIMw7vGHoOQJgkAh/NUiCli1qRnJ\n" +72"FYd6cHMJJK5gF2FqQ7tdbA26pS06bkIEvil2M5wyKKWOydOa/pr1LgMf9KxljJ8J\n" +73"XlAOO/mGZGkYmWnQaQuBIDyWunWYlhsyCXMa8AScgs0uUeQp19tO7R0f03q/JXoZ\n" +74"1At1gZiMS7SdQaRWP5q+FunAeFWjsFE=\n" +75"-----END CERTIFICATE-----";7677private static final String RESP_CERT_1_SUBJ =78"CN=SelfSignedResponder, OU=Validation Services, O=FakeCompany";7980private static X509Certificate cert = null;8182// The expected DER-encoding for a byName ResponderId derived83// from RESP_CERT_184private static final byte[] EXP_NAME_ID_BYTES = {85-95, 84, 48, 82, 49, 20, 48, 18,866, 3, 85, 4, 10, 19, 11, 70,8797, 107, 101, 67, 111, 109, 112, 97,88110, 121, 49, 28, 48, 26, 6, 3,8985, 4, 11, 19, 19, 86, 97, 108,90105, 100, 97, 116, 105, 111, 110, 32,9183, 101, 114, 118, 105, 99, 101, 115,9249, 28, 48, 26, 6, 3, 85, 4,933, 19, 19, 83, 101, 108, 102, 83,94105, 103, 110, 101, 100, 82, 101, 115,95112, 111, 110, 100, 101, 11496};9798// The expected DER-encoding for a byKey ResponderId derived99// from RESP_CERT_1100private static final byte[] EXP_KEY_ID_BYTES = {101-94, 22, 4, 20, 27, 79, 71, 106,102-60, -109, 97, -92, -56, -121, -16, -79,103-59, 95, -21, 112, -107, 117, 46, -6104};105106// The DER encoding of a byKey ResponderId, but using an107// incorrect explicit tagging (CONTEXT CONSTRUCTED 3)108private static final byte[] INV_EXPLICIT_TAG_KEY_ID = {109-93, 22, 4, 20, 27, 79, 71, 106,110-60, -109, 97, -92, -56, -121, -16, -79,111-59, 95, -21, 112, -107, 117, 46, -6112};113114// These two ResponderId objects will have objects attached to them115// after the pos_CtorByName and pos_CtorByKeyId tests run. Those116// two tests should always be the first two that run.117public static ResponderId respByName;118public static ResponderId respByKeyId;119120public static void main(String[] args) throws Exception {121List<TestCase> testList = new ArrayList<>();122123testList.add(pos_CtorByName);124testList.add(pos_CtorByKeyId);125testList.add(pos_CtorByEncoding);126testList.add(neg_CtorByEncoding);127testList.add(pos_Equality);128testList.add(pos_GetEncoded);129testList.add(pos_GetRespName);130testList.add(pos_GetRespKeyId);131132// Load the certificate object we can use for subsequent tests133CertificateFactory cf = CertificateFactory.getInstance("X.509");134cert = (X509Certificate)cf.generateCertificate(135new ByteArrayInputStream(RESP_CERT_1.getBytes()));136137System.out.println("============ Tests ============");138int testNo = 0;139int numberFailed = 0;140Map.Entry<Boolean, String> result;141for (TestCase test : testList) {142System.out.println("Test " + ++testNo + ": " + test.getName());143result = test.runTest();144System.out.print("Result: " + (result.getKey() ? "PASS" : "FAIL"));145System.out.println(" " +146(result.getValue() != null ? result.getValue() : ""));147System.out.println("-------------------------------------------");148if (!result.getKey()) {149numberFailed++;150}151}152System.out.println("End Results: " + (testList.size() - numberFailed) +153" Passed" + ", " + numberFailed + " Failed.");154if (numberFailed > 0) {155throw new RuntimeException(156"One or more tests failed, see test output for details");157}158}159160private static void dumpHexBytes(byte[] data) {161if (data != null) {162for (int i = 0; i < data.length; i++) {163if (i % 16 == 0 && i != 0) {164System.out.print("\n");165}166System.out.print(String.format("%02X ", data[i]));167}168System.out.print("\n");169}170}171172public interface TestCase {173String getName();174Map.Entry<Boolean, String> runTest();175}176177public static final TestCase pos_CtorByName = new TestCase() {178@Override179public String getName() {180return "CTOR Test (by-name)";181}182183@Override184public Map.Entry<Boolean, String> runTest() {185Boolean pass = Boolean.FALSE;186String message = null;187try {188respByName = new ResponderId(cert.getSubjectX500Principal());189pass = Boolean.TRUE;190} catch (Exception e) {191e.printStackTrace(System.out);192message = e.getClass().getName();193}194195return new AbstractMap.SimpleEntry<>(pass, message);196}197};198199public static final TestCase pos_CtorByKeyId = new TestCase() {200@Override201public String getName() {202return "CTOR Test (by-keyID)";203}204205@Override206public Map.Entry<Boolean, String> runTest() {207Boolean pass = Boolean.FALSE;208String message = null;209try {210respByKeyId = new ResponderId(cert.getPublicKey());211pass = Boolean.TRUE;212} catch (Exception e) {213e.printStackTrace(System.out);214message = e.getClass().getName();215}216217return new AbstractMap.SimpleEntry<>(pass, message);218}219};220221public static final TestCase pos_CtorByEncoding = new TestCase() {222@Override223public String getName() {224return "CTOR Test (encoded bytes)";225}226227@Override228public Map.Entry<Boolean, String> runTest() {229Boolean pass = Boolean.FALSE;230String message = null;231try {232ResponderId ridByNameBytes = new ResponderId(EXP_NAME_ID_BYTES);233ResponderId ridByKeyIdBytes = new ResponderId(EXP_KEY_ID_BYTES);234235if (!ridByNameBytes.equals(respByName)) {236throw new RuntimeException(237"Equals failed: respNameFromBytes vs. respByName");238} else if (!ridByKeyIdBytes.equals(respByKeyId)) {239throw new RuntimeException(240"Equals failed: respKeyFromBytes vs. respByKeyId");241}242pass = Boolean.TRUE;243} catch (Exception e) {244e.printStackTrace(System.out);245message = e.getClass().getName();246}247248return new AbstractMap.SimpleEntry<>(pass, message);249}250};251252public static final TestCase neg_CtorByEncoding = new TestCase() {253@Override254public String getName() {255return "CTOR Test (by encoding, unknown explicit tag)";256}257258@Override259public Map.Entry<Boolean, String> runTest() {260Boolean pass = Boolean.FALSE;261String message = null;262try {263ResponderId ridByKeyIdBytes =264new ResponderId(INV_EXPLICIT_TAG_KEY_ID);265throw new RuntimeException("Expected IOException not thrown");266} catch (IOException ioe) {267// Make sure it's the IOException we're looking for268if (ioe.getMessage().contains("Invalid ResponderId content")) {269pass = Boolean.TRUE;270} else {271ioe.printStackTrace(System.out);272message = ioe.getClass().getName();273}274} catch (Exception e) {275e.printStackTrace(System.out);276message = e.getClass().getName();277}278279return new AbstractMap.SimpleEntry<>(pass, message);280}281};282283284public static final TestCase pos_Equality = new TestCase() {285@Override286public String getName() {287return "Simple Equality Test";288}289290@Override291public Map.Entry<Boolean, String> runTest() {292Boolean pass = Boolean.FALSE;293String message = null;294295try {296// byName ResponderId equality test297ResponderId compName =298new ResponderId(new X500Principal(RESP_CERT_1_SUBJ));299if (!respByName.equals(compName)) {300message = "ResponderId mismatch in byName comparison";301} else if (respByKeyId.equals(compName)) {302message = "Invalid ResponderId match in byKeyId comparison";303} else {304pass = Boolean.TRUE;305}306} catch (Exception e) {307e.printStackTrace(System.out);308message = e.getClass().getName();309}310311return new AbstractMap.SimpleEntry<>(pass, message);312}313};314315public static final TestCase pos_GetEncoded = new TestCase() {316@Override317public String getName() {318return "Get Encoded Value";319}320321@Override322public Map.Entry<Boolean, String> runTest() {323Boolean pass = Boolean.FALSE;324String message = null;325326try {327// Pull out byName and byKey encodings, they should match328// the expected values329if (!Arrays.equals(respByName.getEncoded(), EXP_NAME_ID_BYTES)) {330message = "ResponderId byName encoding did not " +331"match expected value";332} else if (!Arrays.equals(respByKeyId.getEncoded(), EXP_KEY_ID_BYTES)) {333message = "ResponderId byKeyId encoding did not " +334"match expected value";335} else {336pass = Boolean.TRUE;337}338} catch (Exception e) {339e.printStackTrace(System.out);340message = e.getClass().getName();341}342343return new AbstractMap.SimpleEntry<>(pass, message);344}345};346347public static final TestCase pos_GetRespName = new TestCase() {348@Override349public String getName() {350return "Get Underlying Responder Name";351}352353@Override354public Map.Entry<Boolean, String> runTest() {355Boolean pass = Boolean.FALSE;356String message = null;357358try {359// Test methods for pulling out the underlying360// X500Principal object361X500Principal testPrincipal =362new X500Principal(RESP_CERT_1_SUBJ);363if (!respByName.getResponderName().equals(testPrincipal)) {364message = "ResponderId Name did not match expected value";365} else if (respByKeyId.getResponderName() != null) {366message = "Non-null responder name returned from " +367"ResponderId constructed byKey";368} else {369pass = Boolean.TRUE;370}371} catch (Exception e) {372e.printStackTrace(System.out);373message = e.getClass().getName();374}375376return new AbstractMap.SimpleEntry<>(pass, message);377}378};379380public static final TestCase pos_GetRespKeyId = new TestCase() {381@Override382public String getName() {383return "Get Underlying Responder Key ID";384}385386@Override387public Map.Entry<Boolean, String> runTest() {388Boolean pass = Boolean.FALSE;389String message = null;390391try {392// Test methods for pulling out the underlying393// KeyIdentifier object. Note: There is a minute chance that394// an RSA public key, once hashed into a key ID might collide395// with the one extracted from the certificate used to create396// respByKeyId. This is so unlikely to happen it is considered397// virtually impossible.398KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");399kpg.initialize(2048);400KeyPair rsaKey = kpg.generateKeyPair();401KeyIdentifier testKeyId = new KeyIdentifier(rsaKey.getPublic());402403if (respByKeyId.getKeyIdentifier().equals(testKeyId)) {404message = "Unexpected match in ResponderId Key ID";405} else if (respByName.getKeyIdentifier() != null) {406message = "Non-null key ID returned from " +407"ResponderId constructed byName";408} else {409pass = Boolean.TRUE;410}411} catch (Exception e) {412e.printStackTrace(System.out);413message = e.getClass().getName();414}415416return new AbstractMap.SimpleEntry<>(pass, message);417}418};419420}421422423