You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by bl...@apache.org on 2003/11/13 10:28:55 UTC

cvs commit: xml-security/src/org/apache/xml/security/keys KeyInfo.java

blautenb    2003/11/13 01:28:55

  Modified:    src/org/apache/xml/security/encryption XMLCipher.java
               src/org/apache/xml/security/keys KeyInfo.java
  Log:
  Implementation of very basic ability to decrypt EncryptedKey
  
  Revision  Changes    Path
  1.8       +180 -9    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.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- XMLCipher.java	12 Nov 2003 11:24:04 -0000	1.7
  +++ XMLCipher.java	13 Nov 2003 09:28:55 -0000	1.8
  @@ -194,6 +194,7 @@
       private Map enc2JCE;
   	private Map enc2IV;
   	private Key localKey;
  +	private Key localKEK;
   
       /**
        * Creates a new <code>XMLCipher</code>.
  @@ -286,6 +287,8 @@
           }
   
           instance.algorithm = transformation;
  +		instance.localKey = null;
  +		instance.localKEK = null;
   
           try {
               String jceAlgorithm = (String) instance.enc2JCE.get(transformation);
  @@ -331,6 +334,8 @@
   
           instance.algorithm = transformation;
   		instance.requestedJCEProvider = provider;
  +		instance.localKey = null;
  +		instance.localKEK = null;
   
           try {
               String jceAlgorithm = (String) instance.enc2JCE.get(transformation);
  @@ -375,6 +380,24 @@
   
       }
   
  +	/**
  +	 * Set a Key Encryption Key.
  +	 * <p>
  +	 * The Key Encryption Key (KEK) is used for encrypting/decrypting
  +	 * EncryptedKey elements.  By setting this separately, the XMLCipher
  +	 * class can know whether a key applies to the data part or wrapped key
  +	 * part of an encrypted object.
  +	 *
  +	 * @param kek The key to use for de/encrypting key data
  +	 */
  +
  +	public void setKEK(Key kek) {
  +
  +		localKEK = kek;
  +
  +	}
  +  
  +
       /**
        * Encrypts an <code>Element</code> and replaces it with its encrypted
        * counterpart in the context <code>Document</code>, that is, the
  @@ -829,8 +852,48 @@
   		return (encryptedData);
       }
   
  +    /**
  +     * Returns an <code>EncryptedKey</code> interface. Use this operation if
  +     * you want to load an <code>EncryptedKey</code> structure from a DOM 
  +	 * structure and manipulate the contents.
  +     *
  +     * @param context the context <code>Document</code>.
  +     * @param element the <code>Element</code> that will be loaded
  +     * @throws XMLEncryptionException.
  +     */
  +
  +    public EncryptedKey loadEncryptedKey(Document context, Element element) 
  +		throws XMLEncryptionException {
  +        logger.debug("Loading encrypted key...");
  +        if(null == context)
  +            logger.error("Context document unexpectedly null...");
  +        if(null == element)
  +            logger.error("Element unexpectedly null...");
  +        if(cipherMode != DECRYPT_MODE)
  +            logger.error("XMLCipher unexpectedly not in DECRYPT_MODE...");
  +
  +        instance.contextDocument = context;
  +        EncryptedKey encryptedKey = factory.newEncryptedKey(element);
  +
  +		return (encryptedKey);
  +    }
  +
  +    /**
  +     * Returns an <code>EncryptedKey</code> interface. Use this operation if
  +     * you want to load an <code>EncryptedKey</code> structure from a DOM 
  +	 * structure and manipulate the contents.
  +	 *
  +	 * Assumes that the context document is the document that owns the element
  +     *
  +     * @param element the <code>Element</code> that will be loaded
  +     * @throws XMLEncryptionException.
  +     */
   
  +    public EncryptedKey loadEncryptedKey(Element element) 
  +		throws XMLEncryptionException {
   
  +		return (loadEncryptedKey(element.getOwnerDocument(), element));
  +    }
   
       /**
        * Decrypts an <code>EncryptedKey</code> object.
  @@ -840,6 +903,97 @@
           return (null);
       }
   
  +	/**
  +	 * Decrypt a key from a passed in EncryptedKey structure
  +	 *
  +	 * @param encryptedKey Previously loaded EncryptedKey that needs
  +	 * to be decrypted.
  +	 * @param keyType a URI indicated the type of key that is wrapped
  +	 * @returns a key corresponding to the give type
  +	 */
  +
  +	public Key decryptKey(EncryptedKey encryptedKey, String algorithm) throws
  +	            XMLEncryptionException {
  +
  +        logger.debug("Decrypting key from previously loaded EncryptedKey...");
  +
  +        if(cipherMode != DECRYPT_MODE)
  +            logger.error("XMLCipher unexpectedly not in DECRYPT_MODE...");
  +
  +		if (localKEK == 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");
  +		}
  +
  +		CipherData cipherData = encryptedKey.getCipherData();
  +        String base64EncodedEncryptedOctets = null;
  +
  +        if (cipherData.getDataType() == CipherData.REFERENCE_TYPE) {
  +            // retrieve the cipher text
  +        } else if (cipherData.getDataType() == CipherData.VALUE_TYPE) {
  +            CipherValue cipherValue = cipherData.getCipherValue();
  +            base64EncodedEncryptedOctets = new String(cipherValue.getValue());
  +        } else {
  +            // complain...
  +        }
  +        logger.debug("Encrypted octets:\n" + base64EncodedEncryptedOctets);
  +
  +        byte[] encryptedBytes = null;
  +
  +        try {
  +			encryptedBytes = Base64.decode(base64EncodedEncryptedOctets);
  +        } catch (Base64DecodingException bde) {
  +            throw new XMLEncryptionException("empty", bde);
  +        }
  +
  +		// Now create the working cipher
  +
  +		String jceAlgorithm = 
  +			JCEMapper.translateURItoJCEID(encryptedKey.getEncryptionMethod()
  +										  .getAlgorithm()).getAlgorithmID();
  +		String provider;
  +
  +		if (requestedJCEProvider == null)
  +			provider =
  +				JCEMapper.translateURItoJCEID(encryptedKey
  +											  .getEncryptionMethod()
  +											  .getAlgorithm())
  +				.getProviderId();
  +		else
  +			provider = requestedJCEProvider;
  +
  +		String jceKeyAlgorithm = 
  +			JCEMapper.getJCEKeyAlgorithmFromURI(algorithm, provider);
  +
  +		Cipher c;
  +		try {
  +			c = Cipher.getInstance(jceAlgorithm, provider);
  +		} catch (NoSuchAlgorithmException nsae) {
  +			throw new XMLEncryptionException("empty", nsae);
  +		} catch (NoSuchProviderException nspre) {
  +			throw new XMLEncryptionException("empty", nspre);
  +		} catch (NoSuchPaddingException nspae) {
  +			throw new XMLEncryptionException("empty", nspae);
  +		}
  +
  +		Key ret;
  +
  +		try {		
  +			c.init(Cipher.UNWRAP_MODE, localKEK);
  +			ret = c.unwrap(encryptedBytes, jceKeyAlgorithm, Cipher.SECRET_KEY);
  +			
  +		} catch (InvalidKeyException ike) {
  +			throw new XMLEncryptionException("empty", ike);
  +		} catch (NoSuchAlgorithmException nsae) {
  +			throw new XMLEncryptionException("empty", nsae);
  +		}
  +
  +		return ret;
  +
  +    }
  +		
  +
       /**
        * Removes the contents of a <code>Node</code>.
        *
  @@ -870,6 +1024,12 @@
           if(cipherMode != DECRYPT_MODE)
               logger.error("XMLCipher unexpectedly not in DECRYPT_MODE...");
   
  +		if (localKey == 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");
  +		}
  +
           EncryptedData encryptedData = factory.newEncryptedData(element);
   
           CipherData cipherData = encryptedData.getCipherData();
  @@ -1508,10 +1668,16 @@
   			XMLEncryptionException {
               EncryptedData result = null;
   
  +			NodeList dataElements = element.getElementsByTagNameNS(
  +                    EncryptionConstants.EncryptionSpecNS,
  +                    EncryptionConstants._TAG_CIPHERDATA);
  +
  +			// Need to get the last CipherData found, as earlier ones will
  +			// be for elements in the KeyInfo lists
  +
               Element dataElement =
  -                (Element) element.getElementsByTagNameNS(
  -                    EncryptionConstants.EncryptionSpecNS, 
  -                    EncryptionConstants._TAG_CIPHERDATA).item(0);
  +				(Element) dataElements.item(dataElements.getLength() - 1);
  +
               CipherData data = newCipherData(dataElement);
   
               result = newEncryptedData(data);
  @@ -1599,11 +1765,12 @@
           EncryptedKey newEncryptedKey(Element element) throws
                   XMLEncryptionException {
               EncryptedKey result = null;
  -
  -            Element dataElement =
  -                (Element) element.getElementsByTagNameNS(
  +			NodeList dataElements = element.getElementsByTagNameNS(
                       EncryptionConstants.EncryptionSpecNS,
  -                    EncryptionConstants._TAG_CIPHERDATA).item(0);
  +                    EncryptionConstants._TAG_CIPHERDATA);
  +            Element dataElement =
  +				(Element) dataElements.item(dataElements.getLength() - 1);
  +
               CipherData data = newCipherData(dataElement);
               result = newEncryptedKey(data);
   
  @@ -1633,12 +1800,16 @@
                       encryptionMethodElement));
               }
   
  -            // TODO: Implement
               Element keyInfoElement =
                   (Element) element.getElementsByTagNameNS(
                       Constants.SignatureSpecNS, Constants._TAG_KEYINFO).item(0);
               if (null != keyInfoElement) {
  -                result.setKeyInfo(null);
  +				try {
  +					result.setKeyInfo(new KeyInfo(keyInfoElement, null));
  +				} catch (XMLSecurityException xse) {
  +					throw new XMLEncryptionException("Error loading Key Info", 
  +													 xse);
  +				}
               }
   
               // TODO: Implement
  
  
  
  1.13      +28 -1     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.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- KeyInfo.java	29 Apr 2003 21:36:53 -0000	1.12
  +++ KeyInfo.java	13 Nov 2003 09:28:55 -0000	1.13
  @@ -67,6 +67,8 @@
   import javax.crypto.SecretKey;
   
   import org.apache.xml.security.Init;
  +import org.apache.xml.security.encryption.EncryptedKey;
  +import org.apache.xml.security.encryption.XMLCipher;
   import org.apache.xml.security.exceptions.XMLSecurityException;
   import org.apache.xml.security.keys.content.KeyName;
   import org.apache.xml.security.keys.content.KeyValue;
  @@ -82,6 +84,7 @@
   import org.apache.xml.security.keys.keyresolver.KeyResolverSpi;
   import org.apache.xml.security.keys.storage.StorageResolver;
   import org.apache.xml.security.transforms.Transforms;
  +import org.apache.xml.security.utils.EncryptionConstants;
   import org.apache.xml.security.utils.Constants;
   import org.apache.xml.security.utils.IdResolver;
   import org.apache.xml.security.utils.SignatureElementProxy;
  @@ -588,6 +591,30 @@
            return null;
         }
      }
  +
  +   /**
  +	* Method itemEncryptedKey
  +	*
  +	* @param i
  +	*
  +	* @throws XMLEncryptionException
  +	*/
  +
  +	public EncryptedKey itemEncryptedKey(int i) throws XMLSecurityException {
  +
  +		Element e = 
  +			this.getChildElementLocalName(i, 
  +										  EncryptionConstants.EncryptionSpecNS,
  +										  EncryptionConstants._TAG_ENCRYPTEDKEY);
  +
  +		if (e != null) {
  +			XMLCipher cipher = XMLCipher.getInstance(XMLCipher.TRIPLEDES);
  +			return cipher.loadEncryptedKey(e);
  +		}
  +		else {
  +			return null;
  +		}
  +	}
   
      /**
       * Method itemUnknownElement