From 5f86fb1e5af2fdd19dc37ecde5f04ef0fdcb3c23 Mon Sep 17 00:00:00 2001 From: Patrick Dowler Date: Thu, 22 Feb 2024 15:00:36 -0800 Subject: [PATCH] SSLUtil: cleanup cruft --- .../java/ca/nrc/cadc/auth/SSLUtilTest.java | 123 +----------- .../main/java/ca/nrc/cadc/auth/SSLUtil.java | 190 ++---------------- 2 files changed, 18 insertions(+), 295 deletions(-) diff --git a/cadc-util/src/intTest/java/ca/nrc/cadc/auth/SSLUtilTest.java b/cadc-util/src/intTest/java/ca/nrc/cadc/auth/SSLUtilTest.java index 746a0609..6c971e8f 100644 --- a/cadc-util/src/intTest/java/ca/nrc/cadc/auth/SSLUtilTest.java +++ b/cadc-util/src/intTest/java/ca/nrc/cadc/auth/SSLUtilTest.java @@ -107,62 +107,6 @@ public class SSLUtilTest private static String TEST_PEM_FN = "proxy.pem"; private static File SSL_PEM; - private static final String KEY_512 = - "-----BEGIN RSA PRIVATE KEY-----\n" + - "MIIBOgIBAAJBAOvm3yk/tr7/8ZaT584T54tOviYIpoWWRfwDgd176c0kTfTj43+C\n" + - "BgxFcequf5mY51mgD7v38krRA3+xXi/igfsCAwEAAQJBAMqVrQXGcpDaScVPZV1j\n" + - "WJAY4lDVUvQb1iQTev4SwPjqUy8H/f0Zt+Bezwf1LaxcHcCFA6QnDxHw6l99/5zw\n" + - "p7kCIQD+4rfjcZyYUKwF0C2deKEgvZUjpiLYVyh/G4qKfT2sPwIhAOzu598CHLLn\n" + - "LSZoBRJtjuhAr1zUrfkoBsNHQwTKi6tFAiBOpKtyXPKhOHrrTEFWzgqBLJ2gozkr\n" + - "ITFYjqnfcycdRwIgbMW1L31hvYRCBxrEEVS4wclIeJ6vC+6jRC1ICEAQZN0CIFe+\n" + - "Az22zN/URBRVBK32tI2axHy/j80Asysh+hxalp1F\n" + - "-----END RSA PRIVATE KEY-----\n"; - private static final String KEY_1024 = - "-----BEGIN RSA PRIVATE KEY-----\n" + - "MIICXQIBAAKBgQDIcNIXiBAPuOjTNWJUbsI+TR1FSXNGM2bv2naU7pKQ0OWI+DDs\n" + - "K1xlctgTi5WrfsMjPKoM+0zpVT5qjUrHyFatbTu9tYjLblPmi/yzOEOIloqZ8lF1\n" + - "hrkUG98f8IBbgx4BbkXscVKdP9awngEpIYrZt3QXLUwUP+oF2PCGH5f+nwIDAQAB\n" + - "AoGBAI5gVVuRspb4aaldSjNfWWqXrCsDOXasHHpTW9f+fu2O9PyOD3Iyerc1FHcN\n" + - "t4rRyBrHhKMj/kXf3y4gnvW6QJY8MM+lHx7oubS8O5aqVexKa8dawQNHvMfLz9PU\n" + - "OuN7X2+rvLS3+qPUtL2LiklCSsrr137M4OBNdfTcZKqAEaLBAkEA/QWsVzhx526D\n" + - "HCBaJ6cgfo6Ravqjg17DDe/yt5iC+dQzGMozWJdHjOS/066aZNF4Els4iSVWdIT5\n" + - "KqBmgjBFZQJBAMrMub59uqqHFGQzWgtOdQamiyeEwr48+a3xHUYy5p+1h7TWetHR\n" + - "OQTFOwGfpv8h7RGd2TS3fxzK+G5LKIUChbMCQQDF+rpvROtbe017pJTmkg8K9+Mx\n" + - "IgzvriZRsX7pyZwyf6e7rfufRj/mLtcqe2SznnOlaVtDdMPBSIrun7OWCs9BAkB6\n" + - "V2b2dALYPQUgLZp0l7AhgvcPsBeLjF1TgdGXN73JO0nS3lDZos4zAojGQfoMj/rk\n" + - "VcVi+A/G3utgHhcjppHhAkBpxQmU1fAB2wKVNtTh2puPmKt+g1wob1yZASRJEadZ\n" + - "5QR7EgNAJtdlouvJcdnTXHJS9JazpcS3061+u2TfgIvx\n" + - "-----END RSA PRIVATE KEY-----\n"; - private static final String KEY_2048 = - "-----BEGIN RSA PRIVATE KEY-----\n" + - "MIIEpgIBAAKCAQEA4Sa+glBzaztCbgZ90uFm5sfjSWUtZCGTw1UwcIFsQtkBa1ut\n" + - "gn1b2LtGevctPoXMreMq4f/5TNAtJuBOHP+2Xv+mIBBbm+zJwTAfk9I0/6wcNlkS\n" + - "FKhSqkpvwSv6+ecQ6R5zUrQv1aMwI392GyAiY8Jo4J6UVGKe7+YY1yvWraVFZYzB\n" + - "FeCNb9Qlo4X+uyZRjz0JJmJZE8H6USmrAa1DPQoWRBpJPJ/sIM1ejTz6lLyC3A54\n" + - "e0Nh+z8dPfUVzBySOgPzypPbuyEaVEFlmm+PqyrfoSIgNQNeOY0SbyhN374xpSHz\n" + - "PBPUPgy5qwidQB4+XN6YQlumz/i4+UnPdvR8jwIDAQABAoIBAQCmGGn0QptS4O2Z\n" + - "s0pBNq0t1QoUTAKXWrniIMdSR/fwvJvycjhnCkmmckmFTzFebWBYazxoauijxPN6\n" + - "OYEGnZIRNPF9t/OM7LrNvM2exDT65CIP6dePy7joDW+yBtroXpC4GRGkUm7zYKaT\n" + - "mWUsj6EvDO1Hv1TXh8WOXqW2no2JnP7OgCcVCGSR4/o6vBaDlUUBSiA3HIG7LWwW\n" + - "uin3LdZ8Z6CuwwlSdc758LIRlE5cGwU4Q4GH34KsMHJU0xkTaeSoYWFWo9xBTlQ1\n" + - "KuLgrYHeomKItiQTeXmuD8hepqhBkrH7tgfPcDrwmOlgarrJ1YK5Ve+i2nyHWVlP\n" + - "/g8DyrgxAoGBAP+08fzjxht5P7wW1E3QY+79NG5vO9uc+joG5X2U0Yu/98UWa1P5\n" + - "d6cbHQQuML0g7MfgRK52h80x+0xPcNewOmCX8vkYLpOqW++UOxH0Czam6igxeprV\n" + - "5WIYg5RB1QhbhQ5rRc4O+l61Yi9hdQBnJNfFbSqU373JLZpD6T5wdCXnAoGBAOFo\n" + - "1I8PEZaxiNz3qGb5LHEeSHRqQHKBQMoUcjAThA8T/Dx7uo3EkrKptyxJdpNeJbnE\n" + - "/GJsjXrElAHJqST1wmQzC3KLhgmKZliB4Ewk1foIfid36T0w/+RrlW2kwqinkr+H\n" + - "UOCSKnsQE8+xeGZ68WxmrBDmGnf5AtS9dfa6cc8ZAoGBAItxhoFNSSyUS3Br1qz0\n" + - "lnqutBgBKthRW5enSSDZtggK0Lg2yKLLqTeErqcn9UY+HUHGiE3Hr7jzp8HulG/a\n" + - "14rzcfnq+QNn5Kja4fehaTgNgCYZDW5AdM2w5phD6kObfQzm7PM48coSChAiimaE\n" + - "2O+d5zFQbE8X1XmJzTlSo9RDAoGBAKA/BXXasZdfCTyF+DuUgwq8C6hvbPe6edPv\n" + - "6ynQhf6uJ5DcKUjl6aCIVQdwBpNHyCwkJYTXRVF09P+8XLpA2Pyg6U96b0TTFmVv\n" + - "l4SqX1CMvxrR/YeaESFTdnznN9fsob/1tAKjBv5L9LmfokfAuWdmKocs/r4x0dhq\n" + - "BLXt4EDpAoGBAKN61XJ+kwO6FkxuyTlbv458Bc9toFyPqSaafJeEp/p3KdLMlphr\n" + - "0GzdeGNkrNfseVbSAjnlO2zmmhVe6Oz3oIR4d/5Hb8QEZi8f7nOZboufITyGTtYG\n" + - "LfVRkN/AuTrxRxWQDbZOo55ACoJA3DH7/BMOXhf9RikjrvESLtCWzsf2\n" + - "-----END RSA PRIVATE KEY-----\n"; - - /** * @throws java.lang.Exception */ @@ -173,21 +117,6 @@ public static void setUpBeforeClass() throws Exception SSL_PEM = FileUtil.getFileFromResource(TEST_PEM_FN, SSLUtilTest.class); } - @Test - public void testReadPem() throws Exception - { - try - { - X509CertificateChain chain = SSLUtil.readPemCertificateAndKey(SSL_PEM); - Assert.assertNotNull("Null chain", chain); - } - catch (Throwable t) - { - t.printStackTrace(); - Assert.fail("unexpected exception: " + t); - } - } - @Test public void testGetSocketFactoryFromNull() throws Exception { @@ -228,7 +157,8 @@ public void testGetSocketFactoryFromFile() throws Exception } @Test - public void testReadCert() { + public void testReadUserCert() { + // test reading a real user cert try { File f = new File(System.getProperty("user.home") + "/.ssl/" + System.getProperty("user.name") + ".pem"); log.info("in: " + f.getAbsolutePath()); @@ -251,6 +181,7 @@ public void testReadCert() { @Test public void testReadUserProxyCert() { + // test reading a proxy cert (usually made from user cert using openssl) try { File f = new File(System.getProperty("user.home") + "/.ssl/cadcproxy.pem"); log.info("in: " + f.getAbsolutePath()); @@ -273,6 +204,7 @@ public void testReadUserProxyCert() { @Test public void testReadProxyCert() { + // test read proxy.pem found in classpath (test resources) try { File f = SSL_PEM; log.info("in: " + f.getAbsolutePath()); @@ -307,53 +239,6 @@ public void testInitSSL() throws Exception } } - public void testHTTPS(URL url) throws Exception - { - HttpURLConnection.setFollowRedirects(false); - - SSLSocketFactory sf = SSLUtil.getSocketFactory(SSL_PEM); - URLConnection con = url.openConnection(); - - log.debug("URLConnection type: " + con.getClass().getName()); - HttpsURLConnection ucon = (HttpsURLConnection) con; - ucon.setSSLSocketFactory(sf); - log.debug("status: " + ucon.getResponseCode()); - log.debug("content-length: " + ucon.getContentLength()); - log.debug("content-type: " + ucon.getContentType()); - } - - @Test - public void testGoogleHTTPS() throws Exception - { - try - { - URL url = new URL("https://www.google.com/"); - log.debug("test URL: " + url); - testHTTPS(url); - } - catch (Throwable t) - { - t.printStackTrace(); - Assert.fail("unexpected exception: " + t); - } - } - - @Test - public void testCadcHTTPS() throws Exception - { - try - { - URL url = new URL("https://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/"); - log.debug("test URL: " + url); - testHTTPS(url); - } - catch (Throwable t) - { - t.printStackTrace(); - Assert.fail("unexpected exception: " + t); - } - } - @Test public void testValidSubject() throws Exception { diff --git a/cadc-util/src/main/java/ca/nrc/cadc/auth/SSLUtil.java b/cadc-util/src/main/java/ca/nrc/cadc/auth/SSLUtil.java index 71e53039..5d821fa0 100644 --- a/cadc-util/src/main/java/ca/nrc/cadc/auth/SSLUtil.java +++ b/cadc-util/src/main/java/ca/nrc/cadc/auth/SSLUtil.java @@ -148,19 +148,20 @@ public class SSLUtil { private static final char[] THE_PASSWORD = CERT_ALIAS.toCharArray(); + /** + * Set the default SSL socket factory with client credentials. This is in + * use in some test code but it's a very bad idea because all threads in the + * JVM use those same credentials for SSL (https) calls. + * + * @param pemFile + * @deprecated + */ + @Deprecated public static void initSSL(File pemFile) { SSLSocketFactory sf = getSocketFactory(pemFile); HttpsURLConnection.setDefaultSSLSocketFactory(sf); } - /** - * Initialise the default SSL socket factory so that all HTTPS connections use - * the provided key store to authenticate (when the server requires client - * authentication). - * - * @param pemFile proxy certificate - * @return configured SSL socket factory - */ public static SSLSocketFactory getSocketFactory(File pemFile) { X509CertificateChain chain; try { @@ -211,15 +212,9 @@ public static SSLSocketFactory getSocketFactory(X509CertificateChain chain) { ks = getKeyStore(chain.getChain(), chain.getPrivateKey()); } - return getSocketFactory(ks, ts); - } - - // may in future try to support other KeyStore formats - @Deprecated - private static SSLSocketFactory getSocketFactory(KeyStore keyStore, KeyStore trustStore) { - KeyManagerFactory kmf = getKeyManagerFactory(keyStore); - TrustManagerFactory tmf = getTrustManagerFactory(trustStore); - SSLContext ctx = getContext(kmf, tmf, keyStore); + KeyManagerFactory kmf = getKeyManagerFactory(ks); + TrustManagerFactory tmf = getTrustManagerFactory(ts); + SSLContext ctx = getContext(kmf, tmf, ks); SSLSocketFactory sf = ctx.getSocketFactory(); return sf; } @@ -239,38 +234,6 @@ public static Subject createSubject(File certKeyFile) { } } - @Deprecated - private static byte[] getPrivateKey(byte[] certBuf) throws IOException { - BufferedReader rdr = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(certBuf))); - String line = rdr.readLine(); - StringBuilder base64 = new StringBuilder(); - while (line != null) { - if (line.matches("-----BEGIN.*PRIVATE KEY-----")) { - // log.debug(line); - line = rdr.readLine(); - while (line != null && !line.startsWith("-----END ")) { - - // log.debug(line + " (" + line.length() + ")"); - base64.append(line.trim()); - line = rdr.readLine(); - } - // log.debug(line); - line = null; // break from outer loop - } else { - line = rdr.readLine(); - } - } - rdr.close(); - String encoded = base64.toString(); - // log.debug("RSA PRIVATE KEY: " + encoded); - // log.debug("RSA private key: " + encoded.length() + " chars"); - // now: base64 -> byte[] - byte[] ret = Base64.decode(encoded); - // log.debug("RSA private key: " + ret.length + " bytes"); - - return ret; - } - /** * Extracts all the certificates from the argument, decodes them from base64 to * byte[] and concatenates all the certificates preserving the order. @@ -379,13 +342,6 @@ public static X509Certificate[] readCertificateChain(byte[] certBuf) throws Cert return chain; } - @Deprecated - private static PrivateKey readPrivateKey(File keyFile) - throws InvalidKeySpecException, NoSuchAlgorithmException, IOException { - byte[] priv = FileUtil.readFile(keyFile); - return readPrivateKey(priv); - } - // needed by cadc-cdp-server public static PrivateKey readPrivateKey(byte[] bytesPrivateKey) throws InvalidKeySpecException, NoSuchAlgorithmException, IOException { @@ -418,35 +374,6 @@ private static KeyStore getKeyStore(Certificate[] chain, PrivateKey pk) { } } - // currently broken trying to parse the openssl-generated pkcs12 file - @Deprecated - private static KeyStore readPKCS12(File f) { - InputStream istream = null; - try { - istream = new FileInputStream(f); - KeyStore ks = KeyStore.getInstance("PKCS12"); - // assume a non-password-protected proxy cert - ks.load(istream, THE_PASSWORD); - return ks; - } catch (KeyStoreException ex) { - throw new RuntimeException("failed to find KeyStore for " + KEYSTORE_TYPE, ex); - } catch (FileNotFoundException ex) { - throw new RuntimeException("failed to find key store file " + f, ex); - } catch (IOException ex) { - throw new RuntimeException("failed to read key store file " + f, ex); - } catch (NoSuchAlgorithmException ex) { - throw new RuntimeException("failed to check integtrity of key store file " + f, ex); - } catch (CertificateException ex) { - throw new RuntimeException("failed to load proxy certificate(s) from key store file " + f, ex); - } finally { - try { - istream.close(); - } catch (Throwable ignore) { - // do nothing - } - } - } - private static KeyManagerFactory getKeyManagerFactory(KeyStore keyStore) { String da = KEYMANAGER_ALGORITHM; try { @@ -611,96 +538,7 @@ private static X509CertificateChain readPEM(PEMParser parser) return new X509CertificateChain(chain, privateKey); } - - - /* - public static RSAPrivateCrtKeySpec parseKeySpec(byte[] code) throws IOException { - DerParser parser = new DerParser(code); - - Asn1Object sequence = parser.read(); - if (sequence.getType() != Asn1Object.SEQUENCE) { - throw new IOException("Invalid DER: not a sequence"); //$NON-NLS-1$ - } - - // Parse inside the sequence - parser = sequence.getParser(); - log.debug("type integer: " + Asn1Object.INTEGER); - - Asn1Object version = parser.read(); - log.debug("version: " + version.getType() + " " + version.getLength()); - - BigInteger modulus = parser.read().getInteger(); - BigInteger publicExp = parser.read().getInteger(); - BigInteger privateExp = parser.read().getInteger(); - BigInteger prime1 = parser.read().getInteger(); - BigInteger prime2 = parser.read().getInteger(); - BigInteger exp1 = parser.read().getInteger(); - BigInteger exp2 = parser.read().getInteger(); - BigInteger crtCoef = parser.read().getInteger(); - - RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2, exp1, - exp2, crtCoef); - - return keySpec; - - } - */ - - /** - * Build a PEM string of certificates and private key. - * - * @param certChainStr - * @param bytesPrivateKey - * @return certificate chain and private key as a PEM encoded string - */ - private static String buildPEM(String certChainStr, byte[] bytesPrivateKey) { - if (certChainStr == null || bytesPrivateKey == null) { - throw new RuntimeException("Cannot build PEM of cert & privateKey. An argument is null."); - } - - // locate the 2nd occurance of CERT_BEGIN string - int posCertEnd = certChainStr.indexOf(X509CertificateChain.CERT_END); - if (posCertEnd == -1) { - throw new RuntimeException("Cannot find END mark of certificate."); - } - - StringBuilder sb = new StringBuilder(); - sb.append(X509CertificateChain.PRIVATE_KEY_BEGIN); - sb.append(X509CertificateChain.NEW_LINE); - sb.append(Base64.encodeLines64(bytesPrivateKey)); - sb.append(X509CertificateChain.PRIVATE_KEY_END); - String privateKeyStr = sb.toString(); - - int posSecondCertStart = certChainStr.indexOf(X509CertificateChain.CERT_BEGIN, posCertEnd); - if (posSecondCertStart == -1) { - // this is an end user certificate, number of certificates==1 - return (certChainStr + X509CertificateChain.NEW_LINE + privateKeyStr); - } else { - // private key goes in between the first and second - // certificate in the chain - String certStrPart1 = certChainStr.substring(0, posSecondCertStart); - String certStrPart2 = certChainStr.substring(posSecondCertStart); - return (certStrPart1 + privateKeyStr + X509CertificateChain.NEW_LINE + certStrPart2); - } - } - - /** - * @param chain - * @return certificate chain and private key as a PEM encoded string - */ - // THIS IS NOT WORKING. - // getEncoded() in privateKey does not use the encoding expected by PEM. - - /* - * public static String writePEMCertificateAndKey(X509CertificateChain chain) { - * if (chain == null) return null; - * - * String certChainStr = chain.certificateString(); byte[] bytesPrivateKey = - * chain.getPrivateKey().getEncoded(); if (certChainStr == null || - * bytesPrivateKey == null) return null; String pemStr = - * SSLUtil.buildPEM(certChainStr, bytesPrivateKey); return pemStr; } - */ - + /** * Checks whether the subject's certificate credentials are valid at a given * date. If date is missing, current time is used as reference. @@ -718,7 +556,7 @@ public static void validateSubject(Subject subject, Date date) throws CertificateException, CertificateExpiredException, CertificateNotYetValidException { if (subject != null) { Set certs = subject.getPublicCredentials(X509CertificateChain.class); - if (certs.size() == 0) { + if (certs.isEmpty()) { // subject without certs throw new CertificateException("No certificates associated with subject"); }