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