You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2016/02/02 11:48:12 UTC

svn commit: r1728075 - in /webservices/wss4j/branches/2_1_x-fixes: ws-security-common/src/main/java/org/apache/wss4j/common/util/ ws-security-dom/src/main/java/org/apache/wss4j/dom/message/ ws-security-dom/src/test/java/org/apache/wss4j/dom/message/ ws...

Author: coheigea
Date: Tue Feb  2 10:48:12 2016
New Revision: 1728075

URL: http://svn.apache.org/viewvc?rev=1728075&view=rev
Log:
[WSS-566] - AES_128_GCM does not work for attachments

Modified:
    webservices/wss4j/branches/2_1_x-fixes/ws-security-common/src/main/java/org/apache/wss4j/common/util/AttachmentUtils.java
    webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncrypt.java
    webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/AttachmentTest.java
    webservices/wss4j/branches/2_1_x-fixes/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptOutputProcessor.java
    webservices/wss4j/branches/2_1_x-fixes/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/AttachmentTest.java

Modified: webservices/wss4j/branches/2_1_x-fixes/ws-security-common/src/main/java/org/apache/wss4j/common/util/AttachmentUtils.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/2_1_x-fixes/ws-security-common/src/main/java/org/apache/wss4j/common/util/AttachmentUtils.java?rev=1728075&r1=1728074&r2=1728075&view=diff
==============================================================================
--- webservices/wss4j/branches/2_1_x-fixes/ws-security-common/src/main/java/org/apache/wss4j/common/util/AttachmentUtils.java (original)
+++ webservices/wss4j/branches/2_1_x-fixes/ws-security-common/src/main/java/org/apache/wss4j/common/util/AttachmentUtils.java Tue Feb  2 10:48:12 2016
@@ -20,12 +20,12 @@ package org.apache.wss4j.common.util;
 
 import org.apache.wss4j.common.ext.Attachment;
 import org.apache.wss4j.common.ext.WSSecurityException;
-import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.algorithms.JCEMapper;
+import org.apache.xml.security.encryption.XMLCipherUtil;
 import org.apache.xml.security.stax.impl.util.MultiInputStream;
 
 import javax.crypto.Cipher;
 import javax.crypto.CipherInputStream;
-import javax.crypto.spec.IvParameterSpec;
 import javax.mail.internet.MimeUtility;
 
 import java.io.*;
@@ -34,6 +34,7 @@ import java.nio.charset.StandardCharsets
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.Key;
+import java.security.spec.AlgorithmParameterSpec;
 import java.util.*;
 
 public final class AttachmentUtils {
@@ -479,23 +480,19 @@ public final class AttachmentUtils {
             private boolean firstRead = true;
 
             private void initCipher() throws IOException {
-                // For now, we only work with Block ciphers, so this will work.
-                // This should probably be put into the JCE mapper.
-                int ivLen = cipher.getBlockSize();
-                if (XMLCipher.AES_128_GCM.equals(encAlgo) || XMLCipher.AES_192_GCM.equals(encAlgo) 
-                    || XMLCipher.AES_256_GCM.equals(encAlgo)) {
-                    ivLen = 12;
-                }
-
+                int ivLen = JCEMapper.getIVLengthFromURI(encAlgo) / 8;
                 byte[] ivBytes = new byte[ivLen];
+
                 int read = super.in.read(ivBytes, 0, ivLen);
                 while (read != ivLen) {
                     read += super.in.read(ivBytes, read, ivLen - read);
                 }
-                IvParameterSpec iv = new IvParameterSpec(ivBytes);
+                
+                AlgorithmParameterSpec paramSpec = 
+                    XMLCipherUtil.constructBlockCipherParameters(encAlgo, ivBytes, AttachmentUtils.class);
 
                 try {
-                    cipher.init(Cipher.DECRYPT_MODE, key, iv);
+                    cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
                 } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
                     throw new IOException(e);
                 }

Modified: webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncrypt.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncrypt.java?rev=1728075&r1=1728074&r2=1728075&view=diff
==============================================================================
--- webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncrypt.java (original)
+++ webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncrypt.java Tue Feb  2 10:48:12 2016
@@ -20,6 +20,7 @@
 package org.apache.wss4j.dom.message;
 
 import java.security.cert.X509Certificate;
+import java.security.spec.AlgorithmParameterSpec;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -30,7 +31,6 @@ import javax.crypto.Cipher;
 import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
@@ -59,8 +59,10 @@ import org.apache.xml.security.encryptio
 import org.apache.xml.security.encryption.EncryptedData;
 import org.apache.xml.security.encryption.TransformSerializer;
 import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.encryption.XMLCipherUtil;
 import org.apache.xml.security.encryption.XMLEncryptionException;
 import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.stax.ext.XMLSecurityConstants;
 import org.apache.xml.security.utils.Base64;
 import org.apache.xml.security.utils.EncryptionConstants;
 import org.w3c.dom.Attr;
@@ -631,17 +633,13 @@ public class WSSecEncrypt extends WSSecE
         String jceAlgorithm = JCEMapper.translateURItoJCEID(encryptionAlgorithm);
         try {
             Cipher cipher = Cipher.getInstance(jceAlgorithm);
+            
+            int ivLen = JCEMapper.getIVLengthFromURI(encryptionAlgorithm) / 8;
+            byte[] iv = XMLSecurityConstants.generateBytes(ivLen);
+            AlgorithmParameterSpec paramSpec = 
+                XMLCipherUtil.constructBlockCipherParameters(encryptionAlgorithm, iv, WSSecEncrypt.class);
+            cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
 
-            // The Spec mandates a 96-bit IV for GCM algorithms
-            if (XMLCipher.AES_128_GCM.equals(encryptionAlgorithm)
-                || XMLCipher.AES_192_GCM.equals(encryptionAlgorithm)
-                || XMLCipher.AES_256_GCM.equals(encryptionAlgorithm)) {
-                byte[] iv = WSSecurityUtil.generateNonce(12);
-                IvParameterSpec paramSpec = new IvParameterSpec(iv);
-                cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
-            } else {
-                cipher.init(Cipher.ENCRYPT_MODE, secretKey);
-            }
             return cipher;
         } catch (Exception e) {
             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);

Modified: webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/AttachmentTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/AttachmentTest.java?rev=1728075&r1=1728074&r2=1728075&view=diff
==============================================================================
--- webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/AttachmentTest.java (original)
+++ webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/AttachmentTest.java Tue Feb  2 10:48:12 2016
@@ -411,6 +411,66 @@ public class AttachmentTest extends Asse
     }
 
     @Test
+    public void testXMLAttachmentContentEncryptionGCM() throws Exception {
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecEncrypt encrypt = new WSSecEncrypt();
+        encrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        encrypt.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+        encrypt.setSymmetricEncAlgorithm(WSConstants.AES_128_GCM);
+
+        WSSecHeader secHeader = new WSSecHeader(doc);
+        secHeader.insertSecurityHeader();
+
+        encrypt.getParts().add(new WSEncryptionPart("Body", "http://schemas.xmlsoap.org/soap/envelope/", "Content"));
+        encrypt.getParts().add(new WSEncryptionPart("cid:Attachments", "Content"));
+
+        String attachmentId = UUID.randomUUID().toString();
+        final Attachment attachment = new Attachment();
+        attachment.setMimeType("text/xml");
+        attachment.addHeaders(getHeaders(attachmentId));
+        attachment.setId(attachmentId);
+        attachment.setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
+
+        AttachmentCallbackHandler attachmentCallbackHandler =
+            new AttachmentCallbackHandler(Collections.singletonList(attachment));
+        encrypt.setAttachmentCallbackHandler(attachmentCallbackHandler);
+        List<Attachment> encryptedAttachments = attachmentCallbackHandler.getResponseAttachments();
+
+        Document encryptedDoc = encrypt.build(doc, crypto, secHeader);
+
+        if (LOG.isDebugEnabled()) {
+            String outputString = XMLUtils.prettyDocumentToString(encryptedDoc);
+            LOG.debug(outputString);
+        }
+
+        NodeList references = doc.getElementsByTagNameNS(WSConstants.ENC_NS, "DataReference");
+        Assert.assertEquals(2, references.getLength());
+        NodeList cipherReferences = doc.getElementsByTagNameNS(WSConstants.ENC_NS, "CipherReference");
+        Assert.assertEquals(1, cipherReferences.getLength());
+        NodeList encDatas = doc.getElementsByTagNameNS(WSConstants.ENC_NS, "EncryptedData");
+        Assert.assertEquals(2, encDatas.getLength());
+
+        NodeList securityHeaderElement = doc.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
+        Assert.assertEquals(1, securityHeaderElement.getLength());
+        NodeList childs = securityHeaderElement.item(0).getChildNodes();
+        Assert.assertEquals(2, childs.getLength());
+        Assert.assertEquals(childs.item(0).getLocalName(), "EncryptedKey");
+        Assert.assertEquals(childs.item(1).getLocalName(), "EncryptedData");
+
+        attachmentCallbackHandler = new AttachmentCallbackHandler(encryptedAttachments);
+        verify(encryptedDoc, attachmentCallbackHandler);
+
+        Assert.assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
+        Attachment responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(0);
+        byte[] attachmentBytes = readInputStream(responseAttachment.getSourceStream());
+        Assert.assertTrue(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
+        Assert.assertEquals("text/xml", responseAttachment.getMimeType());
+
+        Map<String, String> attHeaders = responseAttachment.getHeaders();
+        Assert.assertEquals(6, attHeaders.size());
+    }
+    
+    @Test
     public void testInvalidXMLAttachmentContentEncryption() throws Exception {
         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
         WSSecEncrypt encrypt = new WSSecEncrypt();

Modified: webservices/wss4j/branches/2_1_x-fixes/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/2_1_x-fixes/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptOutputProcessor.java?rev=1728075&r1=1728074&r2=1728075&view=diff
==============================================================================
--- webservices/wss4j/branches/2_1_x-fixes/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptOutputProcessor.java (original)
+++ webservices/wss4j/branches/2_1_x-fixes/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptOutputProcessor.java Tue Feb  2 10:48:12 2016
@@ -21,6 +21,7 @@ package org.apache.wss4j.stax.impl.proce
 import java.io.OutputStream;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.security.spec.AlgorithmParameterSpec;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -28,7 +29,6 @@ import java.util.List;
 import java.util.Map;
 
 import javax.crypto.Cipher;
-import javax.crypto.spec.IvParameterSpec;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
 import javax.xml.namespace.QName;
@@ -45,6 +45,8 @@ import org.apache.wss4j.stax.ext.WSSCons
 import org.apache.wss4j.stax.ext.WSSSecurityProperties;
 import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
 import org.apache.wss4j.stax.utils.WSSUtils;
+import org.apache.xml.security.algorithms.JCEMapper;
+import org.apache.xml.security.encryption.XMLCipherUtil;
 import org.apache.xml.security.exceptions.XMLSecurityException;
 import org.apache.xml.security.stax.config.JCEAlgorithmMapper;
 import org.apache.xml.security.stax.config.TransformerAlgorithmMapper;
@@ -263,15 +265,13 @@ public class EncryptOutputProcessor exte
                 Cipher cipher = null;
                 try {
                     cipher = Cipher.getInstance(jceAlgorithm);
+                    
+                    int ivLen = JCEMapper.getIVLengthFromURI(encryptionSymAlgorithm) / 8;
+                    byte[] iv = XMLSecurityConstants.generateBytes(ivLen);
+                    AlgorithmParameterSpec paramSpec = 
+                        XMLCipherUtil.constructBlockCipherParameters(encryptionSymAlgorithm, iv, this.getClass());
+                    cipher.init(Cipher.ENCRYPT_MODE, encryptionPartDef.getSymmetricKey(), paramSpec);
 
-                    // The Spec mandates a 96-bit IV for GCM algorithms
-                    if ("AES/GCM/NoPadding".equals(cipher.getAlgorithm())) {
-                        byte[] temp = XMLSecurityConstants.generateBytes(12);
-                        IvParameterSpec ivParameterSpec = new IvParameterSpec(temp);
-                        cipher.init(Cipher.ENCRYPT_MODE, encryptionPartDef.getSymmetricKey(), ivParameterSpec);
-                    } else {
-                        cipher.init(Cipher.ENCRYPT_MODE, encryptionPartDef.getSymmetricKey());
-                    }
                 } catch (Exception e) {
                     throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
                 }

Modified: webservices/wss4j/branches/2_1_x-fixes/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/AttachmentTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/2_1_x-fixes/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/AttachmentTest.java?rev=1728075&r1=1728074&r2=1728075&view=diff
==============================================================================
--- webservices/wss4j/branches/2_1_x-fixes/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/AttachmentTest.java (original)
+++ webservices/wss4j/branches/2_1_x-fixes/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/AttachmentTest.java Tue Feb  2 10:48:12 2016
@@ -479,6 +479,78 @@ public class AttachmentTest extends Abst
         Map<String, String> attHeaders = responseAttachment.getHeaders();
         Assert.assertEquals(6, attHeaders.size());
     }
+    
+    @Test
+    public void testXMLAttachmentContentEncryptionGCM() throws Exception {
+
+        final String attachmentId = UUID.randomUUID().toString();
+        final Attachment attachment = new Attachment();
+        attachment.setMimeType("text/xml");
+        attachment.addHeaders(getHeaders(attachmentId));
+        attachment.setId(attachmentId);
+        attachment.setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
+        AttachmentCallbackHandler attachmentCallbackHandler =
+            new AttachmentCallbackHandler(Collections.singletonList(attachment));
+        List<Attachment> encryptedAttachments = attachmentCallbackHandler.getResponseAttachments();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        {
+            WSSSecurityProperties securityProperties = new WSSSecurityProperties();
+            List<WSSConstants.Action> actions = new ArrayList<WSSConstants.Action>();
+            actions.add(WSSConstants.ENCRYPT);
+            securityProperties.setActions(actions);
+            securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
+            securityProperties.setEncryptionUser("receiver");
+            securityProperties.addEncryptionPart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Content));
+            securityProperties.addEncryptionPart(new SecurePart("cid:Attachments", SecurePart.Modifier.Content));
+            securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
+            securityProperties.setEncryptionSymAlgorithm(WSSConstants.NS_XENC11_AES128_GCM);
+
+            OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
+            XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
+            XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
+            XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
+            xmlStreamWriter.close();
+
+            Document securedDoc = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
+            
+            NodeList references = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "DataReference");
+            Assert.assertEquals(2, references.getLength());
+            NodeList cipherReferences = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "CipherReference");
+            Assert.assertEquals(1, cipherReferences.getLength());
+            NodeList encDatas = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "EncryptedData");
+            Assert.assertEquals(2, encDatas.getLength());
+
+            NodeList securityHeaderElement = securedDoc.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
+            Assert.assertEquals(1, securityHeaderElement.getLength());
+            NodeList childs = securityHeaderElement.item(0).getChildNodes();
+            Assert.assertEquals(2, childs.getLength());
+            Assert.assertEquals(childs.item(0).getLocalName(), "EncryptedKey");
+            Assert.assertEquals(childs.item(1).getLocalName(), "EncryptedData");
+        }
+
+        attachmentCallbackHandler = new AttachmentCallbackHandler(encryptedAttachments);
+        {
+            WSSSecurityProperties securityProperties = new WSSSecurityProperties();
+            securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
+            securityProperties.setCallbackHandler(new CallbackHandlerImpl());
+            securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
+
+            InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
+            XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
+            StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
+        }
+
+        Assert.assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
+        Attachment responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(0);
+
+        byte[] attachmentBytes = readInputStream(responseAttachment.getSourceStream());
+        Assert.assertTrue(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
+        Assert.assertEquals("text/xml", responseAttachment.getMimeType());
+
+        Map<String, String> attHeaders = responseAttachment.getHeaders();
+        Assert.assertEquals(6, attHeaders.size());
+    }
 
     @Test
     public void testInvalidXMLAttachmentContentEncryption() throws Exception {
@@ -1250,4 +1322,5 @@ public class AttachmentTest extends Abst
             }
         }
     }
+    
 }