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 }