blautenb    2003/11/17 01:27:05

  Modified:    src/org/apache/xml/security/encryption XMLCipher.java
               src/org/apache/xml/security/keys KeyInfo.java
               src_unitTests/org/apache/xml/security/test/encryption
                        BaltimoreEncTest.java XMLCipherTester.java
  Log:
  Implementation of KeyResolver for EncryptedKey elements
  
  Revision  Changes    Path
  1.16      +67 -18    
xml-security/src/org/apache/xml/security/encryption/XMLCipher.java
  
  Index: XMLCipher.java
  ===================================================================
  RCS file: 
/home/cvs/xml-security/src/org/apache/xml/security/encryption/XMLCipher.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- XMLCipher.java    16 Nov 2003 09:32:07 -0000      1.15
  +++ XMLCipher.java    17 Nov 2003 09:27:04 -0000      1.16
  @@ -75,6 +75,7 @@
   import java.util.LinkedList;
   import java.util.List;
   import java.util.Map;
  +import java.util.Vector;
   import javax.crypto.BadPaddingException;
   import javax.crypto.Cipher;
   import javax.crypto.IllegalBlockSizeException;
  @@ -83,6 +84,9 @@
   import javax.xml.parsers.DocumentBuilder;
   import javax.xml.parsers.DocumentBuilderFactory;
   import javax.xml.parsers.ParserConfigurationException;
  +import 
org.apache.xml.security.keys.keyresolver.implementations.EncryptedKeyResolver;
  +import org.apache.xml.security.keys.keyresolver.KeyResolverException;
  +import org.apache.xml.security.keys.keyresolver.KeyResolverSpi;
   import org.apache.xml.security.keys.KeyInfo;
   import org.apache.xml.security.utils.Constants;
   import org.apache.xml.security.utils.EncryptionConstants;
  @@ -1190,13 +1194,29 @@
   
           logger.debug("Decrypting key from previously loaded 
EncryptedKey...");
   
  -        if(_cipherMode != DECRYPT_MODE && _cipherMode != UNWRAP_MODE)
  -            logger.error("XMLCipher unexpectedly not in DECRYPT_MODE...");
  +        if(_cipherMode != UNWRAP_MODE)
  +            logger.error("XMLCipher unexpectedly not in UNWRAP_MODE...");
   
  -             if (_kek == null) {
  -                     // For now take the easy apprach and just throw
  -                     logger.error("XMLCipher::decryptKey called without a 
KEK");
  -                     throw new XMLEncryptionException("Unable to decrypt 
without a KEK");
  +             if (algorithm == null) {
  +                     throw new XMLEncryptionException("Cannot decrypt a key 
without knowing the algorithm");
  +             }
  +
  +             if (_key == null) {
  +
  +                     logger.debug("Trying to find a KEK via key resolvers");
  +
  +                     KeyInfo ki = encryptedKey.getKeyInfo();
  +                     if (ki != null) {
  +                             try {
  +                                     _key = ki.getSecretKey();
  +                             }
  +                             catch (Exception e) {
  +                             }
  +                     }
  +                     if (_key == null) {
  +                             logger.error("XMLCipher::decryptKey called 
without a KEK and cannot resolve");
  +                             throw new XMLEncryptionException("Unable to 
decrypt without a KEK");
  +                     }
                }
   
                // Obtain the encrypted octets 
  @@ -1238,7 +1258,7 @@
                Key ret;
   
                try {           
  -                     c.init(Cipher.UNWRAP_MODE, _kek);
  +                     c.init(Cipher.UNWRAP_MODE, _key);
                        ret = c.unwrap(encryptedBytes, jceKeyAlgorithm, 
Cipher.SECRET_KEY);
                        
                } catch (InvalidKeyException ike) {
  @@ -1253,6 +1273,23 @@
   
       }
                
  +     /**
  +      * Decrypt a key from a passed in EncryptedKey structure.  This version
  +      * is used mainly internally, when  the cipher already has an
  +      * EncryptedData loaded.  The algorithm URI will be read from the 
  +      * EncryptedData
  +      *
  +      * @param encryptedKey Previously loaded EncryptedKey that needs
  +      * to be decrypted.
  +      * @returns a key corresponding to the give type
  +      */
  +
  +     public Key decryptKey(EncryptedKey encryptedKey) throws
  +                 XMLEncryptionException {
  +
  +             return decryptKey(encryptedKey, 
_ed.getEncryptionMethod().getAlgorithm());
  +
  +     }
   
       /**
        * Removes the contents of a <code>Node</code>.
  @@ -1284,12 +1321,6 @@
           if(_cipherMode != DECRYPT_MODE)
               logger.error("XMLCipher unexpectedly not in DECRYPT_MODE...");
   
  -             if (_key == null) {
  -                     // For now take the easy apprach and just throw
  -                     logger.error("XMLCipher::decryptElement called without 
a key");
  -                     throw new XMLEncryptionException("Unable to decrypt 
without a key");
  -             }
  -
                String octets;
                try {
                        octets = new String(decryptToByteArray(element), 
"UTF-8");
  @@ -1360,13 +1391,31 @@
           if(_cipherMode != DECRYPT_MODE)
               logger.error("XMLCipher unexpectedly not in DECRYPT_MODE...");
   
  +        EncryptedData encryptedData = _factory.newEncryptedData(element);
  +
                if (_key == null) {
  -                     // For now take the easy apprach and just throw
  -                     logger.error("XMLCipher::decryptToByteArray called 
without a key");
  -                     throw new XMLEncryptionException("Unable to decrypt 
without a key");
  -             }
   
  -        EncryptedData encryptedData = _factory.newEncryptedData(element);
  +                     KeyInfo ki = encryptedData.getKeyInfo();
  +
  +                     if (ki != null) {
  +                             try {
  +                                     // Add a EncryptedKey resolver
  +                                     ki.registerInternalKeyResolver(
  +                                  new EncryptedKeyResolver(encryptedData.
  +                                                                             
                  getEncryptionMethod().
  +                                                                             
                  getAlgorithm(), 
  +                                                                             
                  _kek));
  +                                     _key = ki.getSecretKey();
  +                             } catch (KeyResolverException kre) {
  +                                     // We will throw in a second...
  +                             }
  +                     }
  +
  +                     if (_key == null) {
  +                             logger.error("XMLCipher::decryptElement called 
without a key and unable to resolve");
  +                             throw new XMLEncryptionException("Unable to 
decrypt without a key");
  +                     }
  +             }
   
                // Obtain the encrypted octets 
                XMLCipherInput cipherInput = new XMLCipherInput(encryptedData);
  
  
  
  1.17      +151 -8    
xml-security/src/org/apache/xml/security/keys/KeyInfo.java
  
  Index: KeyInfo.java
  ===================================================================
  RCS file: 
/home/cvs/xml-security/src/org/apache/xml/security/keys/KeyInfo.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- KeyInfo.java      14 Nov 2003 21:05:41 -0000      1.16
  +++ KeyInfo.java      17 Nov 2003 09:27:05 -0000      1.17
  @@ -749,19 +749,12 @@
      }
   
      /**
  -    * This method returns a secret (symmetric) key. This is for XML 
Encryption.
  -    *
  -    */
  -   public SecretKey getSecretKey() throws KeyResolverException {
  -      return null;
  -   }
  -
  -   /**
       * This method returns the public key.
       *
       *
       * @throws KeyResolverException
       */
  +
      public PublicKey getPublicKey() throws KeyResolverException {
   
         PublicKey pk = this.getPublicKeyFromInternalResolvers();
  @@ -1064,6 +1057,156 @@
   
                           if (cert != null) {
                              return cert;
  +                        }
  +                     }
  +                  }
  +               }
  +            }
  +         }
  +      }
  +
  +      return null;
  +   }
  +
  +   /**
  +    * This method returns a secret (symmetric) key. This is for XML 
Encryption.
  +    *
  +    */
  +   public SecretKey getSecretKey() throws KeyResolverException {
  +      SecretKey sk = this.getSecretKeyFromInternalResolvers();
  +
  +      if (sk != null) {
  +         log.debug("I could find a secret key using the per-KeyInfo key 
resolvers");
  +
  +         return sk;
  +      } else {
  +         log.debug("I couldn't find a secret key using the per-KeyInfo key 
resolvers");
  +      }
  +
  +      sk = this.getSecretKeyFromStaticResolvers();
  +
  +      if (sk != null) {
  +         log.debug("I could find a secret key using the system-wide key 
resolvers");
  +
  +         return sk;
  +      } else {
  +         log.debug("I couldn't find a secret key using the system-wide key 
resolvers");
  +      }
  +
  +      return null;
  +   }
  +
  +   /**
  +    * Searches the library wide keyresolvers for Secret keys
  +    *
  +    *
  +    * @throws KeyResolverException
  +    */
  +
  +   SecretKey getSecretKeyFromStaticResolvers() throws KeyResolverException {
  +
  +      for (int i = 0; i < KeyResolver.length(); i++) {
  +         KeyResolver keyResolver = KeyResolver.item(i);
  +
  +         for (int j = 0;
  +                 j < this._constructionElement.getChildNodes().getLength();
  +                 j++) {
  +            Node currentChild =
  +               this._constructionElement.getChildNodes().item(j);
  +
  +            if (currentChild.getNodeType() == Node.ELEMENT_NODE) {
  +               if (this._storageResolvers.size() == 0) {
  +
  +                  // if we do not have storage resolvers, we verify with null
  +                  StorageResolver storage = null;
  +
  +                  if (keyResolver.canResolve((Element) currentChild,
  +                                             this.getBaseURI(), storage)) {
  +                     SecretKey sk  =
  +                        keyResolver.resolveSecretKey((Element) currentChild,
  +                                                     this.getBaseURI(),
  +                                                     storage);
  +
  +                     if (sk != null) {
  +                        return sk;
  +                     }
  +                  }
  +               } else {
  +                  for (int k = 0; k < this._storageResolvers.size(); k++) {
  +                     StorageResolver storage =
  +                        (StorageResolver) 
this._storageResolvers.elementAt(k);
  +
  +                     if (keyResolver.canResolve((Element) currentChild,
  +                                                this.getBaseURI(), storage)) 
{
  +                        SecretKey sk =
  +                           keyResolver.resolveSecretKey((Element) 
currentChild,
  +                                                        this.getBaseURI(),
  +                                                        storage);
  +
  +                        if (sk != null) {
  +                           return sk;
  +                        }
  +                     }
  +                  }
  +               }
  +            }
  +         }
  +      }
  +      return null;
  +   }
  +
  +   /**
  +    * Searches the per-KeyInfo keyresolvers for secret keys
  +    *
  +    *
  +    * @throws KeyResolverException
  +    */
  +
  +   SecretKey getSecretKeyFromInternalResolvers() throws KeyResolverException 
{
  +
  +      for (int i = 0; i < this.lengthInternalKeyResolver(); i++) {
  +         KeyResolverSpi keyResolver = this.itemInternalKeyResolver(i);
  +
  +         log.debug("Try " + keyResolver.getClass().getName());
  +
  +         for (int j = 0;
  +                 j < this._constructionElement.getChildNodes().getLength();
  +                 j++) {
  +            Node currentChild =
  +               this._constructionElement.getChildNodes().item(j);
  +
  +            if (currentChild.getNodeType() == Node.ELEMENT_NODE) {
  +               if (this._storageResolvers.size() == 0) {
  +
  +                  // if we do not have storage resolvers, we verify with null
  +                  StorageResolver storage = null;
  +
  +                  if (keyResolver.engineCanResolve((Element) currentChild,
  +                                                   this.getBaseURI(),
  +                                                   storage)) {
  +                     SecretKey sk =
  +                        keyResolver
  +                           .engineResolveSecretKey((Element) currentChild, 
this
  +                              .getBaseURI(), storage);
  +
  +                     if (sk != null) {
  +                        return sk;
  +                     }
  +                  }
  +               } else {
  +                  for (int k = 0; k < this._storageResolvers.size(); k++) {
  +                     StorageResolver storage =
  +                        (StorageResolver) 
this._storageResolvers.elementAt(k);
  +
  +                     if (keyResolver.engineCanResolve((Element) currentChild,
  +                                                      this.getBaseURI(),
  +                                                      storage)) {
  +                        SecretKey sk = keyResolver
  +                           .engineResolveSecretKey((Element) currentChild, 
this
  +                              .getBaseURI(), storage);
  +
  +                        if (sk != null) {
  +                           return sk;
                           }
                        }
                     }
  
  
  
  1.9       +14 -4     
xml-security/src_unitTests/org/apache/xml/security/test/encryption/BaltimoreEncTest.java
  
  Index: BaltimoreEncTest.java
  ===================================================================
  RCS file: 
/home/cvs/xml-security/src_unitTests/org/apache/xml/security/test/encryption/BaltimoreEncTest.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- BaltimoreEncTest.java     16 Nov 2003 09:20:32 -0000      1.8
  +++ BaltimoreEncTest.java     17 Nov 2003 09:27:05 -0000      1.9
  @@ -66,6 +66,7 @@
   import java.security.cert.X509Certificate;
   import java.security.spec.PKCS8EncodedKeySpec;
   import java.security.KeyFactory;
  +import java.security.PublicKey;
   import java.security.PrivateKey;
   import java.security.Key;
   import javax.crypto.SecretKey;
  @@ -86,7 +87,11 @@
   import org.apache.xml.security.keys.content.x509.XMLX509Certificate;
   import org.apache.xml.security.keys.content.KeyName;
   import org.apache.xml.security.keys.content.X509Data;
  +import org.apache.xml.security.keys.keyresolver.KeyResolverException;
  +import org.apache.xml.security.keys.keyresolver.KeyResolver;
  +import org.apache.xml.security.keys.storage.StorageResolver;
   import org.apache.xml.security.keys.KeyInfo;
  +import org.apache.xml.security.utils.Constants;
   import org.apache.xml.security.utils.XMLUtils;
   import org.apache.xml.serialize.DOMSerializer;
   import org.apache.xml.serialize.Method;
  @@ -220,9 +225,12 @@
                        KeyFactory.getInstance("RSA");
                        rsaKey = keyFactory.generatePrivate(pkcs8Spec);
        
  -             // Initialise the library and get out of here
  +             // Initialise the library
   
                org.apache.xml.security.Init.init();
  +
  +             // Register our key resolver
  +             
KeyResolver.register("org.apache.xml.security.test.encryption.BobKeyResolver");
        }
   
        /**
  @@ -536,6 +544,7 @@
                Key key = findKey(encryptedData);
                
                cipher.init(XMLCipher.DECRYPT_MODE, key);
  +               
                byte[] dd = cipher.decryptToByteArray(ee);
   
                return dd;
  @@ -551,7 +560,7 @@
         */
   
        public SecretKey mapKeyName(String name) throws Exception {
  -
  +             /*
                if (name.equals("bob")) {
   
                        // Bob is a DESEDE key
  @@ -564,6 +573,7 @@
                        return key;
   
                }
  +             */
                if (name.equals("job")) {
   
                        // Jeb is a AES-128 key
  @@ -645,8 +655,7 @@
                }
                if (kek != null) {
                        XMLCipher cipher = XMLCipher.getInstance();
  -                     cipher.init(XMLCipher.DECRYPT_MODE, null);
  -                     cipher.setKEK(kek);
  +                     cipher.init(XMLCipher.UNWRAP_MODE, kek);
                        key = cipher.decryptKey(encryptedKey,
                                                                        
encryptedData.
                                                                        
getEncryptionMethod().
  @@ -723,4 +732,5 @@
           }
           return (baos.toString());
       }
  +
   }
  
  
  
  1.8       +79 -11    
xml-security/src_unitTests/org/apache/xml/security/test/encryption/XMLCipherTester.java
  
  Index: XMLCipherTester.java
  ===================================================================
  RCS file: 
/home/cvs/xml-security/src_unitTests/org/apache/xml/security/test/encryption/XMLCipherTester.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- XMLCipherTester.java      16 Nov 2003 09:20:32 -0000      1.7
  +++ XMLCipherTester.java      17 Nov 2003 09:27:05 -0000      1.8
  @@ -158,10 +158,10 @@
   
        /**
         * Test encryption using a generated AES 128 bit key that is
  -      * encrypted using a AES 192 bit key.  Then reverse
  +      * encrypted using a AES 192 bit key.  Then reverse using the KEK
         */
   
  -     public void testAES128ElementAES192KWCipher() {
  +     public void testAES128ElementAES192KWCipherUsingKEK() {
   
                Document d = document(); // source
                Document ed = null;
  @@ -182,7 +182,7 @@
   
                        // Generate a traffic key
                        KeyGenerator keygen = KeyGenerator.getInstance("AES");
  -                     keygen.init(192);
  +                     keygen.init(128);
                        Key key = keygen.generateKey();
   
               cipher = XMLCipher.getInstance(XMLCipher.AES_192_KeyWrap);
  @@ -209,8 +209,78 @@
               ee = (Element) 
ed.getElementsByTagName("xenc:EncryptedData").item(0);
               cipher = XMLCipher.getInstance(XMLCipher.AES_128);
               cipher.init(XMLCipher.DECRYPT_MODE, null);
  -                     EncryptedData encryptedData = 
cipher.loadEncryptedData(ed, ee);
  +                     cipher.setKEK(kek);
  +                     dd = cipher.doFinal(ed, ee);
  +
  +            target = toString(dd);
  +
  +        } catch (Exception ex) {
  +            ex.printStackTrace();
  +        }
  +
  +        Assert.assertEquals(source, target);
  +    }
  +  
  +
  +     /**
  +      * Test encryption using a generated AES 192 bit key that is
  +      * encrypted using a 3DES key.  Then reverse by decrypting 
  +      * EncryptedKey by hand
  +      */
  +
  +     public void testAES192ElementAES256KWCipher() {
  +
  +             Document d = document(); // source
  +             Document ed = null;
  +             Document dd = null;
  +             Element e = (Element) 
d.getElementsByTagName(element()).item(index());
  +             Element ee = null;
  +
  +             String source = null;
  +             String target = null;
  +
  +        try {
  +
  +                     source = toString(d);;
  +
  +                     // Set up a Key Encryption Key
  +                     byte[] bits192 = "abcdefghijklmnopqrstuvwx".getBytes();
  +            DESedeKeySpec keySpec = new DESedeKeySpec(bits192);
  +            SecretKeyFactory keyFactory = 
SecretKeyFactory.getInstance("DESede");
  +            Key kek = keyFactory.generateSecret(keySpec);
  +
  +                     // Generate a traffic key
  +                     KeyGenerator keygen = KeyGenerator.getInstance("AES");
  +                     keygen.init(192);
  +                     Key key = keygen.generateKey();
  +
  +            cipher = XMLCipher.getInstance(XMLCipher.TRIPLEDES_KeyWrap);
  +                     cipher.init(XMLCipher.WRAP_MODE, kek);
  +                     EncryptedKey encryptedKey = cipher.encryptKey(d, key);
  +
  +            // encrypt
  +            cipher = XMLCipher.getInstance(XMLCipher.AES_192);
  +            cipher.init(XMLCipher.ENCRYPT_MODE, key);
  +                     EncryptedData builder = cipher.getEncryptedData();
  +
  +                     KeyInfo builderKeyInfo = builder.getKeyInfo();
  +                     if (builderKeyInfo == null) {
  +                             builderKeyInfo = new KeyInfo(d);
  +                             builder.setKeyInfo(builderKeyInfo);
  +                     }
  +
  +                     builderKeyInfo.add(encryptedKey);
  +
  +            ed = cipher.doFinal(d, e);
   
  +            //decrypt
  +                     key = null;
  +            ee = (Element) 
ed.getElementsByTagName("xenc:EncryptedData").item(0);
  +            cipher = XMLCipher.getInstance();
  +            cipher.init(XMLCipher.DECRYPT_MODE, null);
  +
  +                     EncryptedData encryptedData = 
cipher.loadEncryptedData(ed, ee);
  +                     
                        if(encryptedData == null) {
                                System.out.println("ed is null");
                        }
  @@ -220,16 +290,15 @@
                        EncryptedKey ek = 
encryptedData.getKeyInfo().itemEncryptedKey(0);
   
                        if (ek != null) {
  -                             XMLCipher keyCipher = 
XMLCipher.getInstance(XMLCipher.AES_128);
  +                             XMLCipher keyCipher = XMLCipher.getInstance();
                                keyCipher.init(XMLCipher.UNWRAP_MODE, kek);
  -                             keyCipher.setKEK(kek);
                                key = keyCipher.decryptKey(ek, 
encryptedData.getEncryptionMethod().getAlgorithm());
                        }
   
  -            cipher.init(XMLCipher.DECRYPT_MODE, key);
  -                     XMLCipher cipher3 = 
XMLCipher.getInstance(XMLCipher.AES_128);
  -                     cipher3.init(XMLCipher.WRAP_MODE, null);
  -            dd = cipher.doFinal(ed, ee);
  +                     // Create a new cipher just to be paranoid
  +                     XMLCipher cipher3 = XMLCipher.getInstance();
  +                     cipher3.init(XMLCipher.DECRYPT_MODE, key);
  +            dd = cipher3.doFinal(ed, ee);
   
               target = toString(dd);
           } catch (Exception ex) {
  @@ -238,7 +307,6 @@
   
           Assert.assertEquals(source, target);
       }
  -  
   
       public void testTrippleDesElementCipher() {
           Document d = document(); // source
  
  
  

Reply via email to