Credentials file resolver will now load rsa keys in DER-encoded pkcs8.
authorwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 2 Dec 2003 23:24:48 +0000 (23:24 +0000)
committerwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 2 Dec 2003 23:24:48 +0000 (23:24 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@797 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

data/credentials2.xml
src/edu/internet2/middleware/shibboleth/common/Credentials.java
tests/conf/test.pemcrt
tests/conf/test.pkcs8.derkey [new file with mode: 0644]

index 02a5563..548ba36 100644 (file)
@@ -7,8 +7,8 @@
                <Certificate format="PEM">
                        <Path>/conf/test.pemcrt</Path>
                </Certificate>
                <Certificate format="PEM">
                        <Path>/conf/test.pemcrt</Path>
                </Certificate>
-               <Key format="PEM">
-                       <Path>/conf/test.pemkey</Path>
+               <Key format="DER-PKCS8">
+                       <Path>/conf/test.pkcs8.derkey</Path>
                </Key>
        </FileResolver>
 </Credentials>
\ No newline at end of file
                </Key>
        </FileResolver>
 </Credentials>
\ No newline at end of file
index 2bee890..fe599ce 100644 (file)
@@ -45,15 +45,13 @@ import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.UnrecoverableKeyException;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.UnrecoverableKeyException;
-import java.util.Collection;
-import java.util.Hashtable;
-import java.util.Iterator;
-
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Collection;
+import java.util.Hashtable;
 
 import org.apache.log4j.Logger;
 import org.w3c.dom.Element;
 
 import org.apache.log4j.Logger;
 import org.w3c.dom.Element;
@@ -73,8 +71,6 @@ public class Credentials {
 
        public Credentials(Element e) {
 
 
        public Credentials(Element e) {
 
-               //TODO talk to Scott about the possibility of changing "resolver" to "loader", to avoid confusion with the AR
-
                if (!e.getTagName().equals("Credentials")) {
                        throw new IllegalArgumentException();
                }
                if (!e.getTagName().equals("Credentials")) {
                        throw new IllegalArgumentException();
                }
@@ -177,59 +173,86 @@ class FileCredentialResolver implements CredentialResolver {
 
                String certFormat = getCertFormat(e);
                String certPath = getCertPath(e);
 
                String certFormat = getCertFormat(e);
                String certPath = getCertPath(e);
-               String keyFormat = "DER";
-               String keyPath = "/conf/test.pemkey";
+
                log.debug("Certificate Format: (" + certFormat + ").");
                log.debug("Certificate Path: (" + certPath + ").");
                log.debug("Certificate Format: (" + certFormat + ").");
                log.debug("Certificate Path: (" + certPath + ").");
-               
+
                //TODO provider optional
                //TODO other kinds of certs?
                //TODO provider optional
                //TODO other kinds of certs?
+               //TODO provide a way to specify a separate CA bundle
+               Collection chain = null;
                try {
                try {
-               CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
-               Collection chain = certFactory.generateCertificates(new ShibResource(certPath, this.getClass()).getInputStream());
-               if (chain.isEmpty()) {
-                       log.error("File did not contain any valid certificates.");
-                       throw new CredentialFactoryException("File did not contain any valid certificates.");
-               }
-               Iterator iterator = chain.iterator();
-               while (iterator.hasNext()) {
-                       System.err.println(((X509Certificate)iterator.next()).getSubjectDN());
-               }
-               //TODO remove this
-               }catch (Exception p) {
-                       System.err.println(p);
-                       p.printStackTrace();
-               }
-               
+                       CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+                       chain = certFactory.generateCertificates(new ShibResource(certPath, this.getClass()).getInputStream());
+
+                       //TODO probably want to walk the chain and make sure things are kosher
+                       //TODO need to order the chain
+                       if (chain.isEmpty()) {
+                               log.error("File did not contain any valid certificates.");
+                               throw new CredentialFactoryException("File did not contain any valid certificates.");
+                       }
+
+               } catch (IOException p) {
+                       log.error("Could not load resource from specified location (" + certPath + "): " + p);
+                       throw new CredentialFactoryException("Unable to load certificates.");
+               } catch (CertificateException p) {
+                       log.error("Problem parsing certificate at (" + certPath + "): " + p);
+                       throw new CredentialFactoryException("Unable to load certificates.");
+               }
+               String keyFormat = getKeyFormat(e);
+               String keyPath = getKeyPath(e);
+               log.debug("Key Format: (" + keyFormat + ").");
+               log.debug("Key Path: (" + keyPath + ").");
+
+               String keyAlgorithm = "RSA";
+
+               //TODO providers?
+               //TODO support DER, PEM, DER-PKCS8, and PEM-PKCS8?
+               //TODO DSA
+
+               PrivateKey key = null;
+
+               if (keyAlgorithm.equals("RSA") && keyFormat.equals("DER-PKCS8")) {
+                       try {
+                               key = getRSADERKey(new ShibResource(keyPath, this.getClass()).getInputStream());
+                       } catch (IOException ioe) {
+                               log.error("Could not load resource from specified location (" + keyPath + "): " + e);
+                               throw new CredentialFactoryException("Unable to load private key.");
+                       }
+               } else {
+                       log.error("File credential resolver only supports the RSA keys in DER-encoded PKCS8 format (DER-PKCS8).");
+                       throw new CredentialFactoryException("Failed to initialize Credential Resolver.");
+               }
+
+               return new Credential(((X509Certificate[]) chain.toArray(new X509Certificate[0])), key);
+       }
+
+       private PrivateKey getRSADERKey(InputStream inStream) throws CredentialFactoryException {
+
                try {
                try {
-                       
-                       //TODO provider??
-                       //TODO other algorithms
-                                       KeyFactory keyFactory = KeyFactory.getInstance("RSA");
-                                       InputStream keyStream = new ShibResource(certPath, this.getClass()).getInputStream();
-                                       byte[] inputBuffer = new byte[8];
-                                       int i;
-                                       ByteContainer inputBytes = new ByteContainer(400);
-                                       do {
-                                               i = keyStream.read(inputBuffer);
-                                               for (int j = 0; j < i; j++) {
-                                                       inputBytes.append(inputBuffer[j]);
-                                               }
-                                       } while (i > -1);
-
-//TODO other encodings?
-                                       PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(inputBytes.toByteArray());
-                                       PrivateKey key = keyFactory.generatePrivate(keySpec);
-
-                               } catch (Exception p) {
-                                       log.error("Problem reading private key: " + p.getMessage());
-                                       //throw new ExtKeyToolException("Problem reading private key.  Keys should be DER encoded pkcs8 or DER encoded native format.");
+
+                       KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+                       byte[] inputBuffer = new byte[8];
+                       int i;
+                       ByteContainer inputBytes = new ByteContainer(400);
+                       do {
+                               i = inStream.read(inputBuffer);
+                               for (int j = 0; j < i; j++) {
+                                       inputBytes.append(inputBuffer[j]);
                                }
                                }
-               
+                       } while (i > -1);
+
+                       PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(inputBytes.toByteArray());
+
+                       return keyFactory.generatePrivate(keySpec);
+
+               } catch (Exception e) {
+                       log.error("Unable to load private key: " + e);
+                       throw new CredentialFactoryException("Unable to load private key.");
+               }
 
 
-               return new Credential(null, null);
        }
        }
-       
+
        private String getCertFormat(Element e) throws CredentialFactoryException {
 
                NodeList certificateElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "Certificate");
        private String getCertFormat(Element e) throws CredentialFactoryException {
 
                NodeList certificateElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "Certificate");
@@ -240,18 +263,43 @@ class FileCredentialResolver implements CredentialResolver {
                if (certificateElements.getLength() > 1) {
                        log.error("Multiple Certificate path specifications, using first.");
                }
                if (certificateElements.getLength() > 1) {
                        log.error("Multiple Certificate path specifications, using first.");
                }
-               
-               String format = ((Element)certificateElements.item(0)).getAttribute("format");
+
+               String format = ((Element) certificateElements.item(0)).getAttribute("format");
                if (format == null || format.equals("")) {
                        log.debug("No format specified for certificate, using default (PEM) format.");
                        format = "PEM";
                }
                if (format == null || format.equals("")) {
                        log.debug("No format specified for certificate, using default (PEM) format.");
                        format = "PEM";
                }
-               
+
                if ((!format.equals("PEM")) && (!format.equals("DER"))) {
                        log.error("File credential resolver only supports the (DER) and (PEM) formats.");
                        throw new CredentialFactoryException("Failed to initialize Credential Resolver.");
                }
                if ((!format.equals("PEM")) && (!format.equals("DER"))) {
                        log.error("File credential resolver only supports the (DER) and (PEM) formats.");
                        throw new CredentialFactoryException("Failed to initialize Credential Resolver.");
                }
-               
+
+               return format;
+       }
+
+       private String getKeyFormat(Element e) throws CredentialFactoryException {
+
+               NodeList keyElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "Key");
+               if (keyElements.getLength() < 1) {
+                       log.error("Key not specified.");
+                       throw new CredentialFactoryException("File Credential Resolver requires a <Key> specification.");
+               }
+               if (keyElements.getLength() > 1) {
+                       log.error("Multiple Keyf path specifications, using first.");
+               }
+
+               String format = ((Element) keyElements.item(0)).getAttribute("format");
+               if (format == null || format.equals("")) {
+                       log.debug("No format specified for certificate, using default (PEM) format.");
+                       format = "PEM";
+               }
+
+               if (!format.equals("DER-PKCS8")) {
+                       log.error("File credential resolver currently only supports (DER-PKCS8) format.");
+                       throw new CredentialFactoryException("Failed to initialize Credential Resolver.");
+               }
+
                return format;
        }
 
                return format;
        }
 
@@ -265,8 +313,9 @@ class FileCredentialResolver implements CredentialResolver {
                if (certificateElements.getLength() > 1) {
                        log.error("Multiple Certificate path specifications, using first.");
                }
                if (certificateElements.getLength() > 1) {
                        log.error("Multiple Certificate path specifications, using first.");
                }
-               
-               NodeList pathElements = ((Element) certificateElements.item(0)).getElementsByTagNameNS(Credentials.credentialsNamespace, "Path");
+
+               NodeList pathElements =
+                       ((Element) certificateElements.item(0)).getElementsByTagNameNS(Credentials.credentialsNamespace, "Path");
                if (pathElements.getLength() < 1) {
                        log.error("Certificate path not specified.");
                        throw new CredentialFactoryException("File Credential Resolver requires a <Certificate><Path/></Certificate> specification.");
                if (pathElements.getLength() < 1) {
                        log.error("Certificate path not specified.");
                        throw new CredentialFactoryException("File Credential Resolver requires a <Certificate><Path/></Certificate> specification.");
@@ -285,9 +334,39 @@ class FileCredentialResolver implements CredentialResolver {
                }
                return path;
        }
                }
                return path;
        }
-       
-       
-       
+
+       private String getKeyPath(Element e) throws CredentialFactoryException {
+
+               NodeList keyElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "Key");
+               if (keyElements.getLength() < 1) {
+                       log.error("Key not specified.");
+                       throw new CredentialFactoryException("File Credential Resolver requires a <Key> specification.");
+               }
+               if (keyElements.getLength() > 1) {
+                       log.error("Multiple Key path specifications, using first.");
+               }
+
+               NodeList pathElements =
+                       ((Element) keyElements.item(0)).getElementsByTagNameNS(Credentials.credentialsNamespace, "Path");
+               if (pathElements.getLength() < 1) {
+                       log.error("Key path not specified.");
+                       throw new CredentialFactoryException("File Credential Resolver requires a <Key><Path/></Certificate> specification.");
+               }
+               if (pathElements.getLength() > 1) {
+                       log.error("Multiple Key path specifications, using first.");
+               }
+               Node tnode = pathElements.item(0).getFirstChild();
+               String path = null;
+               if (tnode != null && tnode.getNodeType() == Node.TEXT_NODE) {
+                       path = tnode.getNodeValue();
+               }
+               if (path == null || path.equals("")) {
+                       log.error("Key path not specified.");
+                       throw new CredentialFactoryException("File Credential Resolver requires a <Key><Path/></Certificate> specification.");
+               }
+               return path;
+       }
+
        /**
         * Auto-enlarging container for bytes.
         */
        /**
         * Auto-enlarging container for bytes.
         */
@@ -342,9 +421,7 @@ class FileCredentialResolver implements CredentialResolver {
                }
 
        }
                }
 
        }
-       
-       
-       
+
 }
 
 class KeystoreCredentialResolver implements CredentialResolver {
 }
 
 class KeystoreCredentialResolver implements CredentialResolver {
@@ -541,7 +618,6 @@ class KeystoreCredentialResolver implements CredentialResolver {
 class CustomCredentialResolver implements CredentialResolver {
 
        private static Logger log = Logger.getLogger(CustomCredentialResolver.class.getName());
 class CustomCredentialResolver implements CredentialResolver {
 
        private static Logger log = Logger.getLogger(CustomCredentialResolver.class.getName());
-       private CredentialResolver resolver;
 
        public Credential loadCredential(Element e) throws CredentialFactoryException {
 
 
        public Credential loadCredential(Element e) throws CredentialFactoryException {
 
index cf449c9..03202e4 100644 (file)
@@ -11,4 +11,40 @@ d1k3uBUHJXV+OzvMEwz2SS0RxFZDw5MGlwJGqkwe5wPN6QUWzCxvpskCAwEAAaMdMBswDAYDVR0T
 AQH/BAIwADALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEEBQADgYEAhrSMGqkpC0zdL/m37A7g32le
 1kgi9PMJzgviXbG1k4eO+xl6JvSfHMfrcjtcHdH+IWZSEoJsKLhGbSSBcOCX34rm4RqE8h4ahgq7
 cDX2RCaY4D26R2cta7ZvXo7CUgJ7vbybSZ7QbqKs3yZcVXIL5sJXkhbZ3dnZRqiEm2VP9ZY=
 AQH/BAIwADALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEEBQADgYEAhrSMGqkpC0zdL/m37A7g32le
 1kgi9PMJzgviXbG1k4eO+xl6JvSfHMfrcjtcHdH+IWZSEoJsKLhGbSSBcOCX34rm4RqE8h4ahgq7
 cDX2RCaY4D26R2cta7ZvXo7CUgJ7vbybSZ7QbqKs3yZcVXIL5sJXkhbZ3dnZRqiEm2VP9ZY=
------END CERTIFICATE-----
\ No newline at end of file
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC6zCCAlSgAwIBAgICAlYwDQYJKoZIhvcNAQEEBQAwgakxCzAJBgNVBAYTAlVT
+MRIwEAYDVQQIEwlXaXNjb25zaW4xEDAOBgNVBAcTB01hZGlzb24xIDAeBgNVBAoT
+F1VuaXZlcnNpdHkgb2YgV2lzY29uc2luMSswKQYDVQQLEyJEaXZpc2lvbiBvZiBJ
+bmZvcm1hdGlvbiBUZWNobm9sb2d5MSUwIwYDVQQDExxIRVBLSSBNYXN0ZXIgQ0Eg
+LS0gMjAwMjA3MDFBMB4XDTAyMDYzMDIyMzIxNFoXDTI3MDIyMDIyMzIxNFowgakx
+CzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlXaXNjb25zaW4xEDAOBgNVBAcTB01hZGlz
+b24xIDAeBgNVBAoTF1VuaXZlcnNpdHkgb2YgV2lzY29uc2luMSswKQYDVQQLEyJE
+aXZpc2lvbiBvZiBJbmZvcm1hdGlvbiBUZWNobm9sb2d5MSUwIwYDVQQDExxIRVBL
+SSBTZXJ2ZXIgQ0EgLS0gMjAwMjA3MDFBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
+iQKBgQCvImusW7uaRS7xLsi2ZzZuUz6gbfATwxwvtQ+8cuyDpRlhvr1qnghC9Enj
+RH9qpq/Z5FVZ5bqyGziCy0kEPt+2WiZMGRiQEzloi5HNEtz1Nlc7FCJ0HATxtkEU
+hQ96v2DmoIEogPINqLICIqfiraPWFHOp6qDritrdj/fwLptQawIDAQABoyAwHjAP
+BgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBpjANBgkqhkiG9w0BAQQFAAOBgQAt
+txlP3fTyIVMAIm8ddE8Bvk0/5Bhn5KvMAOMtnlCEArcFd4/m+pU4vEDwK6JSIoKf
+N/ySLXlu5ItApeJMWhcqvrczq5BF4/WQZukC1ha6FS2cAmjy35jYWMfVWcdBi9Yi
+M4SJ6gjGf83y9axPpuHcjwxQ5fLqZfnvrWH+1owJhQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC6zCCAlSgAwIBAgICAlQwDQYJKoZIhvcNAQEEBQAwgakxCzAJBgNVBAYTAlVT
+MRIwEAYDVQQIEwlXaXNjb25zaW4xEDAOBgNVBAcTB01hZGlzb24xIDAeBgNVBAoT
+F1VuaXZlcnNpdHkgb2YgV2lzY29uc2luMSswKQYDVQQLEyJEaXZpc2lvbiBvZiBJ
+bmZvcm1hdGlvbiBUZWNobm9sb2d5MSUwIwYDVQQDExxIRVBLSSBNYXN0ZXIgQ0Eg
+LS0gMjAwMjA3MDFBMB4XDTAyMDYzMDIyMTYzOVoXDTI5MTExNjIyMTYzOVowgakx
+CzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlXaXNjb25zaW4xEDAOBgNVBAcTB01hZGlz
+b24xIDAeBgNVBAoTF1VuaXZlcnNpdHkgb2YgV2lzY29uc2luMSswKQYDVQQLEyJE
+aXZpc2lvbiBvZiBJbmZvcm1hdGlvbiBUZWNobm9sb2d5MSUwIwYDVQQDExxIRVBL
+SSBNYXN0ZXIgQ0EgLS0gMjAwMjA3MDFBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
+iQKBgQDJ3FDZym9Ja94DP7TUZXf3Vu3CZwqZzYThgjUT2eBJBYVALISSJ+RjJ2j2
+CYpq3wesSgWHqfrpPnTgTBvn5ZZF9diX6ipAmC0H75nySDY8B5AN1RbmPsAZ51F9
+7Eo+6JZ59BFYgowGXyQpMfhBykBSySnvnOX5ygTCz20LwKkErQIDAQABoyAwHjAP
+BgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBpjANBgkqhkiG9w0BAQQFAAOBgQB1
+8ZXB+KeXbDVkz+b2xVXYmJiWrp73IOvi3DuIuX1n88tbIH0ts7dJLEqr+c0owgtu
+QBqLb9DfPG2GkJ1uOK75wPY6XWusCKDJKMVY/N4ec9ew55MnDlFFvl4C+LkiS2YS
+Ysrh7fFJKKp7Pkc1fxsusK+MBXjVZtq0baXsU637qw==
+-----END CERTIFICATE-----
diff --git a/tests/conf/test.pkcs8.derkey b/tests/conf/test.pkcs8.derkey
new file mode 100644 (file)
index 0000000..51a712d
Binary files /dev/null and b/tests/conf/test.pkcs8.derkey differ