1 /*
   2  * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  *
  26  * @author Sean Mullan
  27  * @author Steve Hanna
  28  *
  29  */
  30 
  31 package jdk.test.lib.security;
  32 
  33 import java.io.ByteArrayInputStream;
  34 import java.io.File;
  35 import java.io.FileInputStream;
  36 import java.io.IOException;
  37 import java.io.InputStream;
  38 import java.nio.file.Files;
  39 import java.nio.file.Path;
  40 import java.nio.file.Paths;
  41 import java.security.KeyFactory;
  42 import java.security.NoSuchAlgorithmException;
  43 import java.security.PrivateKey;
  44 import java.security.cert.CRLException;
  45 import java.security.cert.CertPath;
  46 import java.security.cert.CertPathBuilder;
  47 import java.security.cert.CertPathValidator;
  48 import java.security.cert.CertStore;
  49 import java.security.cert.CertificateException;
  50 import java.security.cert.CertificateFactory;
  51 import java.security.cert.CollectionCertStoreParameters;
  52 import java.security.cert.PKIXBuilderParameters;
  53 import java.security.cert.PKIXCertPathBuilderResult;
  54 import java.security.cert.PKIXCertPathValidatorResult;
  55 import java.security.cert.PKIXParameters;
  56 import java.security.cert.X509CRL;
  57 import java.security.cert.X509Certificate;
  58 import java.security.spec.InvalidKeySpecException;
  59 import java.security.spec.PKCS8EncodedKeySpec;
  60 import java.util.ArrayList;
  61 import java.util.Base64;
  62 import java.util.HashSet;
  63 import java.util.List;
  64 import java.util.Set;
  65 import java.util.function.Predicate;
  66 import java.util.stream.Collectors;
  67 import java.util.stream.Stream;
  68 
  69 /**
  70  * Static utility methods useful for testing certificate/certpath APIs.
  71  */
  72 public class CertUtils {
  73 
  74     private CertUtils() {}
  75 
  76     /*
  77      * Version: 3 (0x2)
  78      * Serial Number:
  79      *     7b:bb:a0:55:00:9d:69:16:1e:cb:e2:ad:25:d1:32:ff:fa:52:1b:05
  80      * Signature Algorithm: sha256WithRSAEncryption
  81      * Issuer: CN = localhost
  82      * Validity
  83      *     Not Before: Aug  1 11:58:25 2019 GMT
  84      *     Not After : Jul 29 11:58:25 2029 GMT
  85      * Subject: CN = localhost
  86      */
  87     public static final String RSA_CERT =
  88             "-----BEGIN CERTIFICATE-----\n" +
  89             "MIIDCTCCAfGgAwIBAgIUe7ugVQCdaRYey+KtJdEy//pSGwUwDQYJKoZIhvcNAQEL\n" +
  90             "BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTE5MDgwMTExNTgyNVoXDTI5MDcy\n" +
  91             "OTExNTgyNVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF\n" +
  92             "AAOCAQ8AMIIBCgKCAQEAxDGfn+GQEErnE1ErBaYpH8+rFgUS/nhFuaKLMNsYMtAY\n" +
  93             "GI7XvnwzSMeYou6tDobi0WMxlnQRSlVEmmT6OPOOC9RLnt2qdU2klXVR5DCzVTrp\n" +
  94             "wX5TILkP+KzePRQFrpi4z6Fx15cIVhP4OdPUd4rwAffD+nYaijQezLuKwdBKBHlt\n" +
  95             "GBGxn978Ppcmx/6qAfFZjhtxJXBM7LzUPkDs6jHy10FK9KkqjmmB6zXM0Rvv8nN3\n" +
  96             "9o55H3LnbO4XSIoRUGwSISSiHEBHbOZyBblDc0yoRAnjqxSDIj5oxessfDt5gG6C\n" +
  97             "LqrUyfLDo7pbmQrdBoH2NEX9yScYVE1MnlRA6LusCQIDAQABo1MwUTAdBgNVHQ4E\n" +
  98             "FgQUbZzwnSvM67UCB3ng5fTGcL24uqUwHwYDVR0jBBgwFoAUbZzwnSvM67UCB3ng\n" +
  99             "5fTGcL24uqUwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAgAtI\n" +
 100             "feN7JySd5HdEqA0/vvCCoBJ/Z9//3OxQyW8NnkmVW3F1eMIWII/vOdYj1WJgq1uK\n" +
 101             "a4GKiUVgEYTVSJxwj3mBmvd9o93Im9BSI0RkGOQOTnCLJNTksAD+2qO4F984xucS\n" +
 102             "/R2BChlbik7+7uPZ7qnhfDmxyMJqtUuze/JkA4IrVssbFM30j70gGjNNd/waBsR2\n" +
 103             "upI29x7LSCdPkXmwUuzUR5/zBHaR4pZ2nQvsfxoP384BvpM1SCNrBUGvxGzDDiGA\n" +
 104             "pOJwIJoTEU7gGaHF8BeEUtC1YbSDWr+dN4IM7uzL6sdVs8xPVxkeptlVU7cDIyiN\n" +
 105             "DPm3K0U4oj/KoFfMHg==\n" +
 106             "-----END CERTIFICATE-----";
 107     public static final String RSA_KEY =
 108             "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDEMZ+f4ZAQSucT\n" +
 109             "USsFpikfz6sWBRL+eEW5oosw2xgy0BgYjte+fDNIx5ii7q0OhuLRYzGWdBFKVUSa\n" +
 110             "ZPo4844L1Eue3ap1TaSVdVHkMLNVOunBflMguQ/4rN49FAWumLjPoXHXlwhWE/g5\n" +
 111             "09R3ivAB98P6dhqKNB7Mu4rB0EoEeW0YEbGf3vw+lybH/qoB8VmOG3ElcEzsvNQ+\n" +
 112             "QOzqMfLXQUr0qSqOaYHrNczRG+/yc3f2jnkfcuds7hdIihFQbBIhJKIcQEds5nIF\n" +
 113             "uUNzTKhECeOrFIMiPmjF6yx8O3mAboIuqtTJ8sOjuluZCt0GgfY0Rf3JJxhUTUye\n" +
 114             "VEDou6wJAgMBAAECggEAFwYn0HB9IpxXr9mnrdsJGnWZg1UHHJvqutVLdmlP1q67\n" +
 115             "FS62POGAdzsNO5m872Z++cmlSR3H5axKB8Bv6P0UH2lDkpo65dc9yFhjSt84PHlU\n" +
 116             "c2Oqx71QFYPb9NkDrbC4h41Pudg8nzVqvQaR+ZFxhxmXgy4XAT8KmkYsC4CxHwMY\n" +
 117             "FYCHsNc8kpyXc7P5bbjpdQHMwpBP3dyo42h8cim8P2c5pKM0ipSm4vD9r8NIbvG7\n" +
 118             "+bzLBC0aJCfL0wY2c8qRD2k5Xl/NRKovya8v6IUCyigyJV5DZMOfRqCMDeMuiaxl\n" +
 119             "cvKqIPO5wxE3Wt36cEPZGO6GI6H+tzXZT0+y0+OfXQKBgQD5kR2GscpFhc+/A9Qn\n" +
 120             "QQxeMHjDqXUjP11Czg+/K2vKjC+RHNIzOh+4jGWNb9nlMSu22IRltRzyDOrPRytB\n" +
 121             "RT2o5rUGSv/oZ/lEMMyHz+xPaBfegYSCkZ3h01iL1fdAUALHtzG5c6S8JXhtWzHk\n" +
 122             "q/dk6iXPfTtSREBkwv7c43vXTwKBgQDJQE0ZvgTSnscA+GkM1R7tH0hqKyk/xeus\n" +
 123             "/xu23EraiIg4qoJ7Lk2IRvOkgotuK/SK+qoWlBr3OwBRzByxBXSdjdciZ5jbOc1g\n" +
 124             "TA4Qwma6R9ukYdW+W95nYmsgyOi0+7tX9oVJatBJGyq3atayUANy8Lun4kSRdurn\n" +
 125             "WibRxuxxJwKBgQCq62vhV9pECwTguWqPB8nEqEXNGz2SSk9A9YdrUf2c1q2tIKQF\n" +
 126             "WYVoCx9x4mzEvwxFSbxDO+r7C0W1d/Rz20wDZR4NlUf2j170CMfLK+eX6p6OUP3D\n" +
 127             "vp72jpxSCNQxQ5rj1N9FN6JXCQKVQqPFDNF+V65VkFsUWJIRcErEVTf3mQKBgAiW\n" +
 128             "AbQTc0k5FOxprLGrdgJPz1sYNE5QN1nOGHSYuWjRYl5oh+CRfSVPQZ3HJAOzRF+Z\n" +
 129             "iiAkeXIKxly3BJJY1TzTjFYfbVoNAUIWfJMieBeCcVB2DBRu/vISNNfVOnheNQPv\n" +
 130             "tIgJUpGL4yqoGDjLSRpiQt9Ku/ooxKTSJ83TWssJAoGAflsMfkS9hdoAcWMUWkPU\n" +
 131             "VMTP/yHshZKJK66uAtLJYvSLXMJAN4uCIobiPM0EsdLxTh1nrL36NmWsTZlMhMsS\n" +
 132             "rPaBIT6f6m2M2+8ixiJoZ1ut2iyKxkkvWcECbXqjWw6ndGyAoL1/7OR5guJliePy\n" +
 133             "axFzqDc4QQBTtrjLYuHGi9k=";
 134 
 135     /*
 136      * Version: 3 (0x2)
 137      * Serial Number:
 138      *     3c:09:6b:31:d7:7c:00:93:b2:79:54:f9:c2:3c:d2:dd:76:56:f0:50
 139      * Signature Algorithm: ecdsa-with-SHA256
 140      * Issuer: CN = localhost
 141      * Validity
 142      *      Not Before: Aug  1 11:58:34 2019 GMT
 143      *      Not After : Jul 29 11:58:34 2029 GMT
 144      * Subject: CN = localhost
 145      */
 146     public static final String ECDSA_CERT =
 147             "-----BEGIN CERTIFICATE-----\n" +
 148             "MIIBfjCCASOgAwIBAgIUPAlrMdd8AJOyeVT5wjzS3XZW8FAwCgYIKoZIzj0EAwIw\n" +
 149             "FDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTE5MDgwMTExNTgzNFoXDTI5MDcyOTEx\n" +
 150             "NTgzNFowFDESMBAGA1UEAwwJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" +
 151             "AQcDQgAEs8ThmP8Xi9aBkB3WPfHRflpk6u44/9NIH4IiRSmbB7jmgCH3rP50izNR\n" +
 152             "va4fKIZUJ0vPCS9zBr4rKVco9Z6qV6NTMFEwHQYDVR0OBBYEFFgf2AXMfO1OpBul\n" +
 153             "ArF1gqmVA04YMB8GA1UdIwQYMBaAFFgf2AXMfO1OpBulArF1gqmVA04YMA8GA1Ud\n" +
 154             "EwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAKWR1yXjBedp6hOoxvZ8n9e8\n" +
 155             "k2ZPdboTfyIRvCw9O4BUAiEAuHsWWs34c3xPCxsyoxbpgkBLwdZ1pZASbCMbgZ59\n" +
 156             "RYo=\n" +
 157             "-----END CERTIFICATE-----";
 158     public static final String ECDSA_KEY =
 159             "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgajTO2cTGJdOUawrQ\n" +
 160             "XqGfGuX6AEevTXQY0hlVHAVx516hRANCAASzxOGY/xeL1oGQHdY98dF+WmTq7jj/\n" +
 161             "00gfgiJFKZsHuOaAIfes/nSLM1G9rh8ohlQnS88JL3MGvispVyj1nqpX";
 162 
 163     /*
 164      * Version: 3 (0x2)
 165         Serial Number:
 166             76:07:da:cb:0f:8a:89:26:72:cb:db:20:ec:df:b2:52:50:01:6a:56
 167         Signature Algorithm: rsassaPss
 168          Hash Algorithm: sha256
 169          Mask Algorithm: mgf1 with sha256
 170           Salt Length: 0xDE
 171          Trailer Field: 0xBC (default)
 172         Issuer: CN = localhost
 173         Validity
 174             Not Before: Aug  1 11:58:40 2019 GMT
 175             Not After : Jul 29 11:58:40 2029 GMT
 176         Subject: CN = localhost
 177      */
 178     public static final String RSASSAPSS_CERT =
 179             "-----BEGIN CERTIFICATE-----\n" +
 180             "MIIDaTCCAiCgAwIBAgIUdgfayw+KiSZyy9sg7N+yUlABalYwPgYJKoZIhvcNAQEK\n" +
 181             "MDGgDTALBglghkgBZQMEAgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBogQC\n" +
 182             "AgDeMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xOTA4MDExMTU4NDBaFw0yOTA3\n" +
 183             "MjkxMTU4NDBaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASAwCwYJKoZIhvcNAQEK\n" +
 184             "A4IBDwAwggEKAoIBAQC5igqwiTdawCKIDmGVXAnYSIj5QIiMW4VzeWj87+bWqMec\n" +
 185             "9uiOkFBI9c1y3CMoAPu9SEBbycAMadExB0pRq93Kz7pO30nyOFwDhvnArqg0e+mn\n" +
 186             "6yaJeYWkQFX0HNS/vBwlVPLSkyuE80Tt1bND7ur4z31hT6H16nDBfx14b9aXW9j0\n" +
 187             "L2zqZbyq4jhbELeBK0DtD1tpmJsYHxXjL174fDQ0dArNjIq529veS9z+FjdpuZTm\n" +
 188             "e3XxOyWofA0EV4t3wN7x5RvI0pTo7Na+15TjTlhwHTuaiUPsOvMg73sI+3OxXGHI\n" +
 189             "GDoOgqliYqHH0SkTYWpZF9Be3Th/R90Qg7Pvzo4HAgMBAAGjUzBRMB0GA1UdDgQW\n" +
 190             "BBRQAfLTSK6mt9aKxrWbHUKsKwrBfDAfBgNVHSMEGDAWgBRQAfLTSK6mt9aKxrWb\n" +
 191             "HUKsKwrBfDAPBgNVHRMBAf8EBTADAQH/MD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZI\n" +
 192             "AWUDBAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIEAgIA3gOCAQEAQPJz\n" +
 193             "TGugNS+wmxe6BGHmWLLsRJAQn/lr+3dJIfkfBlmkc43tSdL5R+5LfkNjE7sCUW4s\n" +
 194             "FFKVlQH8XzHbJH0USNp+yxJBjBv5XpXW+mrhGhCBiIoEXce78irNJLy6dJPIFo/m\n" +
 195             "z4Lt2YS5VassInrBvb9KyNlinpqJ5sjptLM2Nc77Rv/uFOkgTNwyuAi+LYuP1lEm\n" +
 196             "4AZcywjfxBv/mmuZ8oAgPj50cN0gsgQmi/bofiZsK4GrZpSncjMYZvG/C4WF2Zem\n" +
 197             "cd7KZtQoPrv3bSE3gyotN04wE2nFLsaR2gheuv0URitDPAzpv8QV3WjEUt6uaFZi\n" +
 198             "K6deQ/N/JiwhoqjM+Q==\n" +
 199             "-----END CERTIFICATE-----";
 200     public static final String RSASSAPSS_KEY =
 201             "MIIEuwIBADALBgkqhkiG9w0BAQoEggSnMIIEowIBAAKCAQEAuYoKsIk3WsAiiA5h\n" +
 202             "lVwJ2EiI+UCIjFuFc3lo/O/m1qjHnPbojpBQSPXNctwjKAD7vUhAW8nADGnRMQdK\n" +
 203             "Uavdys+6Tt9J8jhcA4b5wK6oNHvpp+smiXmFpEBV9BzUv7wcJVTy0pMrhPNE7dWz\n" +
 204             "Q+7q+M99YU+h9epwwX8deG/Wl1vY9C9s6mW8quI4WxC3gStA7Q9baZibGB8V4y9e\n" +
 205             "+Hw0NHQKzYyKudvb3kvc/hY3abmU5nt18TslqHwNBFeLd8De8eUbyNKU6OzWvteU\n" +
 206             "405YcB07molD7DrzIO97CPtzsVxhyBg6DoKpYmKhx9EpE2FqWRfQXt04f0fdEIOz\n" +
 207             "786OBwIDAQABAoIBAH4eO03st9fUKqTZQbPJMFf4VkM3fpoJzBjGOntUh1D6wVUM\n" +
 208             "8N+XcTtm+hRNVwhmQrhTWIwMA6NsemodToNdlBG8SiQ624Tukn1DTpmPH38ti5I8\n" +
 209             "4aEpHZKcuNCKmIMMVwV5TOWebEKfKgeQ754J1Wbzg4KWIr2KcsLUqS+otfGDsOMK\n" +
 210             "nuIhFQhamtNFzuWSRIYJl5jfNcnXmeTivVNywE0Q/PGD3lLn8xB3Bk6uNTAUFBdc\n" +
 211             "nbK7efViSfuNY+kZbHne+mcSGiBJPSzTfd25+/JhYaKFjPiQsIqPAwnZK80LBdeb\n" +
 212             "lxf3zSzpgbx9Jai+kULZJsrVoReZlS6fxeqzZAECgYEA4jRcR6tEQGImsIT7zBTS\n" +
 213             "FYTsqr0wzuUl2m3mNNQX9ZIKEVJxv9Vevyd4eQIwQRwgPM2U2JLsXPjVFc/fCAJO\n" +
 214             "KuLY5sXog4b0c8cHjA8nbJbmjKHkXfgCnKFGoXvUV13LgFg9DX6hzkCKMJxDO9R+\n" +
 215             "pE9k6HXq58yyDvRBvFOCuYECgYEA0fpxa0gwCmyMKQeFnBPd53rnPOBoW2YKnIzR\n" +
 216             "/X1q6YRFdeRgvcBXScPknU1nvoxAtRqHYDSI3d/sHMzZ+qb0BBoD7i2qjKsSH32u\n" +
 217             "jP5m5+psPebJ0UEH/bTUbETWEu9rt8sapag6Mp1QL6uYZW5OOULCpGYa9KcfX93A\n" +
 218             "hwgeO4cCgYBy+mptg4CNuVYxI2dZtLuUdJxXrRLCF3fGL1Z0Q9pp2HGFnIJ1H9+p\n" +
 219             "CkcSOyqL7d/1CApAi23ZVCH7lE2ppIJXCjd2FeK5+D8JGoGbj5haedl2YlPR795j\n" +
 220             "/xYHvwmP3v0xn6ho05UrYWLckpEaOEim/DQudMGSUVmwgDdpookwAQKBgQCv6RhL\n" +
 221             "wFY+5WEmnl6YuywUWSqQHZBPwdTyAieKLh/7MgzfD0zcqt51td84yTg4slcjYe43\n" +
 222             "8ssW1hmApz2Wd3fGV+UjDK7s2gR8zVYGWLrtX77+vPImlEyVh4DOk3yksF+Vwlm4\n" +
 223             "no7jCFe9GAy8LQTrg7p87+11OO1X6vb4KRzq0QKBgCZD8lN/qHpscBQucx60vToU\n" +
 224             "247vlb9LmzsMFVUeyJhg/v1+1kswIImuYC+X0nO8yF++mD8OyWIZaXZAkmEsU9qF\n" +
 225             "ZCdo4KHSmFTKm6mCPW+5tro3GCsavRZqFHeQF8iVRsN3V86q6wRlMvyYmKMLd0Ko\n" +
 226             "0CyaEnQ+kBtL6IaeVNQV";
 227 
 228     /*
 229      * Version: 3 (0x2)
 230      * Serial Number:
 231      *     49:33:8a:a8:cd:d9:14:f8:09:a1:0c:2f:67:a3:27:a6:fc:df:25:f8
 232      * Signature Algorithm: dsa_with_SHA256
 233      * Issuer: CN = localhost
 234      * Validity
 235      *     Not Before: Aug  1 12:01:30 2019 GMT
 236      *     Not After : Jul 27 12:01:30 2039 GMT
 237      * Subject: CN = localhost
 238      */
 239     public static final String DSA_CERT =
 240             "-----BEGIN CERTIFICATE-----\n" +
 241             "MIIEbzCCBBSgAwIBAgIUSTOKqM3ZFPgJoQwvZ6MnpvzfJfgwCwYJYIZIAWUDBAMC\n" +
 242             "MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xOTA4MDExMjAxMzBaFw0zOTA3Mjcx\n" +
 243             "MjAxMzBaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCA0cwggI5BgcqhkjOOAQBMIIC\n" +
 244             "LAKCAQEAsFMaoryk333Vm0JY8QEu1y0HmQkvp5dlM/4ozMj8l6hx8HYo+LYTQD4e\n" +
 245             "t7b7xUf5sYc4mjxpwbV4uf8Q4G1BHfJCGdGKxKigObsbDqpRRBlubHppOX6F6mRz\n" +
 246             "wgaNRfWqlZbcSa+X82SfagtjMVKrH75eIs74U7EBQRun7XilrDFKuG6c98cY1JFI\n" +
 247             "BpAp/Sw+kEk0LYYgdGIVWhNCunECcqWtdz1AEBzHOiqEthKTzF+o1qxBFCYjOnZo\n" +
 248             "wkgG5fqXDc4Rb0iNyxSQXK/lTi/4r6IABY3u7f5NOhj0GmRbbCA/Ef0i6GQKJqzk\n" +
 249             "hfzTQDwRsvX17xLFTOeNQb26dvm23wIhAL6RNExpfF++/0Ph4mkPqxuDLHWACa/y\n" +
 250             "3VeNr8NjO7ovAoIBABndio/73FVBpnpbFdT1DnqY3IWUbpr40zudROuGWvSd66Ia\n" +
 251             "pNtRb/fcgMm3UjAq92SjbF+Rn+gf1ylm1LCtE4xeN02gxCJnR9/HKmuSTDnVOH5F\n" +
 252             "62yjQaEPZ7rG2cr7fP67YiW1b3nTQSL11y62MVvp+JH1BMVd4gYMop7wG8eRajFr\n" +
 253             "hW3AY6dz5J2w6fywvZTIXzv1cZS7be1adcdYSvkFs9V6bT+lQHKNpqM8aab61Kp9\n" +
 254             "aB3+p39nKYm6KPpc/wuSHs5Ez5C89mLrHB4l6xZAMAWqwkDnUmiRScwfyOIKG8VY\n" +
 255             "2c9GtfZOCB21dupwXGruFH1tcg5IP7wHJddOWCADggEGAAKCAQEAkrNcrwgXKVWc\n" +
 256             "gwv4CAJhRAH0svQChcLI1I5+6FB8KomN4xVW+obJcNag3qbTCd3V3mHu6gITxxkq\n" +
 257             "EoA2zCBQFMAIGW2G1PkqOlBK8K3hOut/IEbWmiMlC51P0AUHBd1NDCY6q96Y+mot\n" +
 258             "ogGc3lMQZK5mWseUirP6Qt43N7Ev57PXypKC5MnQKA2+NEhhiHvDruSBloj9zu+w\n" +
 259             "oNhXZP+0dPBb96eeHwcRj25MSuhY+Jpg2OoU+FzDvx7QDEqkq801EBdr9WOiY9hx\n" +
 260             "DpbUZH3mLYo9tzBwDK8RngPlcwlMpuR/A3pu6qLAGJHnVWb1c9mhNHv+8p5to74k\n" +
 261             "2RqOaSU26aNTMFEwHQYDVR0OBBYEFJ8MbprhtUOkVraW76QALKQnZ6yNMB8GA1Ud\n" +
 262             "IwQYMBaAFJ8MbprhtUOkVraW76QALKQnZ6yNMA8GA1UdEwEB/wQFMAMBAf8wCwYJ\n" +
 263             "YIZIAWUDBAMCA0gAMEUCIHaOTmgo0rK4EWGLruxLiTcHZs1KanLrf9FlKbmur9Ee\n" +
 264             "AiEAnE+fxuTBexuPj2elmnxViUj/UYo/NlC4OarhIO1SCzk=\n" +
 265             "-----END CERTIFICATE-----";
 266     public static final String DSA_KEY =
 267             "MIICZQIBADCCAjkGByqGSM44BAEwggIsAoIBAQCwUxqivKTffdWbQljxAS7XLQeZ\n" +
 268             "CS+nl2Uz/ijMyPyXqHHwdij4thNAPh63tvvFR/mxhziaPGnBtXi5/xDgbUEd8kIZ\n" +
 269             "0YrEqKA5uxsOqlFEGW5semk5foXqZHPCBo1F9aqVltxJr5fzZJ9qC2MxUqsfvl4i\n" +
 270             "zvhTsQFBG6fteKWsMUq4bpz3xxjUkUgGkCn9LD6QSTQthiB0YhVaE0K6cQJypa13\n" +
 271             "PUAQHMc6KoS2EpPMX6jWrEEUJiM6dmjCSAbl+pcNzhFvSI3LFJBcr+VOL/ivogAF\n" +
 272             "je7t/k06GPQaZFtsID8R/SLoZAomrOSF/NNAPBGy9fXvEsVM541Bvbp2+bbfAiEA\n" +
 273             "vpE0TGl8X77/Q+HiaQ+rG4MsdYAJr/LdV42vw2M7ui8CggEAGd2Kj/vcVUGmelsV\n" +
 274             "1PUOepjchZRumvjTO51E64Za9J3rohqk21Fv99yAybdSMCr3ZKNsX5Gf6B/XKWbU\n" +
 275             "sK0TjF43TaDEImdH38cqa5JMOdU4fkXrbKNBoQ9nusbZyvt8/rtiJbVvedNBIvXX\n" +
 276             "LrYxW+n4kfUExV3iBgyinvAbx5FqMWuFbcBjp3PknbDp/LC9lMhfO/VxlLtt7Vp1\n" +
 277             "x1hK+QWz1XptP6VAco2mozxppvrUqn1oHf6nf2cpiboo+lz/C5IezkTPkLz2Yusc\n" +
 278             "HiXrFkAwBarCQOdSaJFJzB/I4gobxVjZz0a19k4IHbV26nBcau4UfW1yDkg/vAcl\n" +
 279             "105YIAQjAiEAvP+ZQ7yzUk8rNgk65U/SF++Eyt+i+WR1UBvGxAEEKIQ=";
 280 
 281     private static final String TEST_SRC = System.getProperty("test.src", ".");
 282 
 283     /**
 284      * Get a PEM-encoded PKCS8 private key from a string.
 285      *
 286      * @param keyAlgo the key algorithm
 287      * @param keyStr string containing the PEM-encoded PKCS8 private key
 288      * @return the private key
 289      * @throws NoSuchAlgorithmException if no Provider supports a KeyFactorySpi
 290      *         implementation for the specified algorithm
 291      * @throws InvalidKeySpecException if the given key specification is
 292      *         inappropriate for this key factory to produce a private key.
 293      */
 294     public static PrivateKey getKeyFromString(String keyAlgo, String keyStr)
 295             throws NoSuchAlgorithmException, InvalidKeySpecException {
 296         KeyFactory keyFactory = KeyFactory.getInstance(keyAlgo);
 297         PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(
 298                 Base64.getMimeDecoder().decode(keyStr));
 299         PrivateKey key = keyFactory.generatePrivate(keySpec);
 300         return key;
 301     }
 302 
 303     /**
 304      * Get a PEM-encoded PKCS8 private key from a file.
 305      *
 306      * @param keyAlgo the key algorithm
 307      * @param keyPath path to file containing the PEM-encoded PKCS8 private key
 308      * @return the private key
 309      * @throws NoSuchAlgorithmException if no Provider supports a KeyFactorySpi
 310      *         implementation for the specified algorithm
 311      * @throws InvalidKeySpecException if the given key specification is
 312      *         inappropriate for this key factory to produce a private key.
 313      */
 314     public static PrivateKey getKeyFromFile(String keyAlgo, String keyPath)
 315             throws NoSuchAlgorithmException, InvalidKeySpecException {
 316         return getKeyFromString(
 317                 keyAlgo,
 318 
 319                 // Filter the below lines if any
 320                 // -----BEGIN PRIVATE KEY-----
 321                 // -----END PRIVATE KEY-----
 322                 readFile(keyPath, line -> !line.startsWith("-----")));
 323     }
 324 
 325     /**
 326      * Get an X.509 certificate from an input stream.
 327      *
 328      * @param input an input stream with the certificate data.
 329      * @return the X509Certificate
 330      * @throws CertificateException on parsing errors.
 331      * @throws IOException on input stream errors.
 332      */
 333     public static X509Certificate getCertFromStream(InputStream input)
 334             throws CertificateException, IOException {
 335         try {
 336             CertificateFactory certFactory
 337                     = CertificateFactory.getInstance("X.509");
 338             return (X509Certificate) certFactory.generateCertificate(input);
 339         } finally {
 340             if (input != null) {
 341                 input.close();
 342             }
 343         }
 344     }
 345 
 346     /**
 347      * Get a PEM-encoded X.509 certificate from a string.
 348      *
 349      * @param cert string containing the PEM-encoded certificate
 350      * @return the X509Certificate
 351      * @throws CertificateException if the certificate type is not supported
 352      *                              or cannot be parsed
 353      * @throws IOException
 354      */
 355     public static X509Certificate getCertFromString(String certStr)
 356             throws CertificateException, IOException {
 357         return getCertFromStream(new ByteArrayInputStream(certStr.getBytes()));
 358     }
 359 
 360     /**
 361      * Get a X.509 certificate from a file.
 362      *
 363      * @param certFilePath path to file containing certificate
 364      * @return the X509Certificate
 365      * @throws CertificateException if the certificate type is not supported
 366      *                              or cannot be parsed
 367      * @throws IOException if the file cannot be opened
 368      */
 369     public static X509Certificate getCertFromFile(String certFilePath)
 370             throws CertificateException, IOException {
 371         return getCertFromStream(
 372                 Files.newInputStream(Paths.get(TEST_SRC, certFilePath)));
 373     }
 374 
 375     /**
 376      * Get a DER-encoded X.509 CRL from a file.
 377      *
 378      * @param crlFilePath path to file containing DER-encoded CRL
 379      * @return the X509CRL
 380      * @throws CertificateException if the crl type is not supported
 381      * @throws CRLException if the crl cannot be parsed
 382      * @throws IOException if the file cannot be opened
 383      */
 384     public static X509CRL getCRLFromFile(String crlFilePath)
 385             throws CertificateException, CRLException, IOException {
 386         File crlFile = new File(TEST_SRC, crlFilePath);
 387         try (FileInputStream fis = new FileInputStream(crlFile)) {
 388             return (X509CRL)
 389                 CertificateFactory.getInstance("X.509").generateCRL(fis);
 390         }
 391     }
 392 
 393     /**
 394      * Get a PEM-encoded X.509 crl from a string.
 395      *
 396      * @param crl string containing the PEM-encoded crl
 397      * @return the X509CRL
 398      * @throws CertificateException if the crl type is not supported
 399      * @throws CRLException if the crl cannot be parsed
 400      */
 401     public static X509CRL getCRLFromString(String crl)
 402             throws CertificateException, CRLException {
 403         byte[] crlBytes = crl.getBytes();
 404         ByteArrayInputStream bais = new ByteArrayInputStream(crlBytes);
 405         return (X509CRL)
 406             CertificateFactory.getInstance("X.509").generateCRL(bais);
 407     }
 408 
 409     /**
 410      * Read a bunch of certs from files and create a CertPath from them.
 411      *
 412      * @param fileNames an array of <code>String</code>s that are file names
 413      * @throws Exception on error
 414      */
 415     public static CertPath buildPath(String [] fileNames) throws Exception {
 416         return buildPath("", fileNames);
 417     }
 418 
 419     /**
 420      * Read a bunch of certs from files and create a CertPath from them.
 421      *
 422      * @param relPath relative path containing certs (must end in
 423      *    file.separator)
 424      * @param fileNames an array of <code>String</code>s that are file names
 425      * @throws Exception on error
 426      */
 427     public static CertPath buildPath(String relPath, String [] fileNames)
 428             throws Exception {
 429         List<X509Certificate> list = new ArrayList<X509Certificate>();
 430         for (int i = 0; i < fileNames.length; i++) {
 431             list.add(0, getCertFromFile(relPath + fileNames[i]));
 432         }
 433         CertificateFactory cf = CertificateFactory.getInstance("X509");
 434         return(cf.generateCertPath(list));
 435     }
 436 
 437 
 438     /**
 439      * Read a bunch of certs from files and create a CertStore from them.
 440      *
 441      * @param fileNames an array of <code>String</code>s that are file names
 442      * @return the <code>CertStore</code> created
 443      * @throws Exception on error
 444      */
 445     public static CertStore createStore(String [] fileNames) throws Exception {
 446         return createStore("", fileNames);
 447     }
 448 
 449     /**
 450      * Read a bunch of certs from files and create a CertStore from them.
 451      *
 452      * @param relPath relative path containing certs (must end in
 453      *    file.separator)
 454      * @param fileNames an array of <code>String</code>s that are file names
 455      * @return the <code>CertStore</code> created
 456      * @throws Exception on error
 457      */
 458     public static CertStore createStore(String relPath, String [] fileNames)
 459             throws Exception {
 460         Set<X509Certificate> certs = new HashSet<X509Certificate>();
 461         for (int i = 0; i < fileNames.length; i++) {
 462             certs.add(getCertFromFile(relPath + fileNames[i]));
 463         }
 464         return CertStore.getInstance("Collection",
 465             new CollectionCertStoreParameters(certs));
 466     }
 467 
 468     /**
 469      * Read a bunch of CRLs from files and create a CertStore from them.
 470      *
 471      * @param fileNames an array of <code>String</code>s that are file names
 472      * @return the <code>CertStore</code> created
 473      * @throws Exception on error
 474      */
 475     public static CertStore createCRLStore(String [] fileNames)
 476             throws Exception {
 477         return createCRLStore("", fileNames);
 478     }
 479 
 480     /**
 481      * Read a bunch of CRLs from files and create a CertStore from them.
 482      *
 483      * @param relPath relative path containing CRLs (must end in file.separator)
 484      * @param fileNames an array of <code>String</code>s that are file names
 485      * @return the <code>CertStore</code> created
 486      * @throws Exception on error
 487      */
 488     public static CertStore createCRLStore(String relPath, String [] fileNames)
 489         throws Exception {
 490         Set<X509CRL> crls = new HashSet<X509CRL>();
 491         for (int i = 0; i < fileNames.length; i++) {
 492             crls.add(getCRLFromFile(relPath + fileNames[i]));
 493         }
 494         return CertStore.getInstance("Collection",
 495                 new CollectionCertStoreParameters(crls));
 496     }
 497 
 498     /**
 499      * Perform a PKIX path build. On failure, throw an exception.
 500      *
 501      * @param params PKIXBuilderParameters to use in validation
 502      * @throws Exception on error
 503      */
 504     public static PKIXCertPathBuilderResult build(PKIXBuilderParameters params)
 505         throws Exception {
 506         CertPathBuilder builder =
 507                 CertPathBuilder.getInstance("PKIX");
 508         return (PKIXCertPathBuilderResult) builder.build(params);
 509     }
 510 
 511     /**
 512      * Perform a PKIX validation. On failure, throw an exception.
 513      *
 514      * @param path CertPath to validate
 515      * @param params PKIXParameters to use in validation
 516      * @throws Exception on error
 517      */
 518     public static PKIXCertPathValidatorResult validate
 519         (CertPath path, PKIXParameters params) throws Exception {
 520         CertPathValidator validator =
 521             CertPathValidator.getInstance("PKIX");
 522         return (PKIXCertPathValidatorResult) validator.validate(path, params);
 523     }
 524 
 525     /**
 526      * Get the content of a file with given filter condition.
 527      *
 528      * @param relativeFilePath path to file that relative to test.src directory.
 529      * @param predicate The condition for filtering file content
 530      * @return the file content
 531      */
 532     private static String readFile(String relativeFilePath,
 533             Predicate<String> predicate) {
 534         Path filePath = Paths.get(TEST_SRC, relativeFilePath);
 535         try (Stream<String> lines = Files.lines(filePath)) {
 536             Stream<String> interStream = null;
 537             if (predicate != null) {
 538                 interStream = lines.filter(predicate);
 539             }
 540             return interStream != null
 541                    ? interStream.collect(Collectors.joining("\n"))
 542                    : lines.collect(Collectors.joining("\n"));
 543         } catch (IOException e) {
 544             throw new RuntimeException("Cannot read file", e);
 545         }
 546     }
 547 }