coheigea commented on code in PR #264:
URL: https://github.com/apache/ws-wss4j/pull/264#discussion_r1464799631


##########
ws-security-dom/src/test/java/org/apache/wss4j/dom/message/EncryptionTest.java:
##########
@@ -313,6 +314,66 @@ public void testEncryptionEncryption() throws Exception {
         verify(encryptedEncryptedDoc, encCrypto, keystoreCallbackHandler);
     }
 
+    /**
+     * Test that encrypt and decrypt a WS-Security envelope.
+     * This test uses the ECDSA-ES algorithm to (wrap) the symmetric key.
+     * <p/>
+     *
+     * @throws Exception Thrown when there is any problem in signing or 
verification
+     */
+    @ParameterizedTest
+    @CsvSource({"xdh, X25519",
+            "xdh, X448",
+            "ec, secp256r1",
+            "ec, secp384r1",
+            "ec, secp521r1",
+    })
+    public void testEncryptionDecryptionECDSA_ES(String algorithm, String 
certAlias) throws Exception {
+        try {
+            if (!JDKTestUtils.isAlgorithmSupportedByJDK(algorithm)) {
+                LOG.info("Add AuxiliaryProvider to execute test with algorithm 
[{}] and cert alias [{}]", algorithm,  certAlias);
+                Security.addProvider(JDKTestUtils.getAuxiliaryProvider());
+            }
+            Crypto encCrypto = 
CryptoFactory.getInstance("wss-ecdh.properties");
+
+            Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+            WSSecHeader secHeader = new WSSecHeader(doc);
+            secHeader.insertSecurityHeader();
+
+            WSSecEncrypt builder = new WSSecEncrypt(secHeader);
+            builder.setUserInfo(certAlias);
+            builder.setKeyEncAlgo(WSConstants.KEYWRAP_AES128);
+            
builder.setKeyAgreementMethod(WSConstants.AGREEMENT_METHOD_ECDH_ES);
+            builder.setDigestAlgorithm(WSS4JConstants.SHA256);
+            builder.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER);
+
+            LOG.info("Before Encryption ...");
+            KeyGenerator keyGen = 
KeyUtils.getKeyGenerator(WSConstants.AES_128_GCM);
+            SecretKey symmetricKey = keyGen.generateKey();
+
+            Document encryptedDoc = builder.build(encCrypto, symmetricKey);
+            LOG.info("After Encryption ....");
+
+            String outputString =
+                    XMLUtils.prettyDocumentToString(encryptedDoc);
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Encrypted message:");
+                LOG.debug(outputString);
+            }
+            assertFalse(outputString.contains("counter_port_type"));

Review Comment:
   Could we add an assertion against outputString that it is actually adding 
KeyAgreement in the test?



##########
ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java:
##########
@@ -142,55 +144,22 @@ public List<WSSecurityEngineResult> handleToken(
             throw new 
WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "noCipher");
         }
 
-        Element keyInfoChildElement = getKeyInfoChildElement(elem, data);
-
         X509Certificate[] certs = null;
         STRParser.REFERENCE_TYPE referenceType = null;
         PublicKey publicKey = null;
         boolean symmetricKeyWrap = 
isSymmetricKeyWrap(encryptedKeyTransportMethod);
-        if (!symmetricKeyWrap) {
-            if 
(SecurityTokenReference.SECURITY_TOKEN_REFERENCE.equals(keyInfoChildElement.getLocalName())
-                && 
WSConstants.WSSE_NS.equals(keyInfoChildElement.getNamespaceURI())) {
-                STRParserParameters parameters = new STRParserParameters();
-                parameters.setData(data);
-                parameters.setStrElement(keyInfoChildElement);
-
-                STRParser strParser = new EncryptedKeySTRParser();
-                STRParserResult parserResult = 
strParser.parseSecurityTokenReference(parameters);
-
-                certs = parserResult.getCertificates();
-                publicKey = parserResult.getPublicKey();
-                referenceType = parserResult.getCertificatesReferenceType();
-            } else {
-                certs = getCertificatesFromX509Data(keyInfoChildElement, data);
-                if (certs == null || certs.length == 0) {
-                    XMLSignatureFactory signatureFactory;
-                    if (provider == null) {
-                        // Try to install the Santuario Provider - fall back 
to the JDK provider if this does
-                        // not work
-                        try {
-                            signatureFactory = 
XMLSignatureFactory.getInstance("DOM", "ApacheXMLDSig");
-                        } catch (NoSuchProviderException ex) {
-                            signatureFactory = 
XMLSignatureFactory.getInstance("DOM");
-                        }
-                    } else {
-                        signatureFactory = 
XMLSignatureFactory.getInstance("DOM", provider);
-                    }
-
-                    publicKey = 
X509Util.parseKeyValue((Element)keyInfoChildElement.getParentNode(),
-                                                       signatureFactory);
-                }
-            }
-
-            if (publicKey == null && (certs == null || certs.length < 1 || 
certs[0] == null)) {
-                throw new WSSecurityException(
-                                          
WSSecurityException.ErrorCode.FAILURE,
-                                          "noCertsFound",
-                                          new Object[] {"decryption (KeyId)"});
-            }
-            if (certs != null && certs.length > 0) {
-                publicKey = certs[0].getPublicKey();
-            }
+        AgreementMethod agreementMethod = null;
+        if (isDHKeyWrap) {
+            // get key agreement method value
+            agreementMethod = 
getAgreementMethodFromElement(keyInfoChildElement);
+            //  get the recipient key info element
+            keyInfoChildElement = 
getRecipientKeyInfoChildElement(agreementMethod);

Review Comment:
   There is a potential NPE here that should be handled



##########
ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java:
##########
@@ -357,6 +358,102 @@ private static byte[] getAsymmetricDecryptedBytes(
         }
     }
 
+    /**
+     * Method decrypts encryptedEphemeralKey using Key Agreement algorithm to 
derive symmetric key
+     * for decryption of the key.
+     *
+     * @param data RequestData context
+     * @param agreementMethod AgreementMethod element
+     * @param encryptedKeyTransportMethod Algorithm used to encrypt the key
+     * @param encryptedEphemeralKey Encrypted ephemeral/transport key
+     * @param privateKey Private key of the recipient
+     * @return Decrypted bytes of the ephemeral/transport key
+     * @throws WSSecurityException if the key decryption fails
+     */
+    private static byte[] getDiffieHellmanDecryptedBytes(
+            RequestData data,
+            AgreementMethod agreementMethod,
+            String encryptedKeyTransportMethod,
+            byte[] encryptedEphemeralKey,
+            PrivateKey privateKey
+    ) throws WSSecurityException {
+
+        SecretKey kek;
+        try {
+            KeyAgreementParameters parameterSpec = 
XMLCipherUtil.constructRecipientKeyAgreementParameters(
+                    encryptedKeyTransportMethod, agreementMethod, privateKey);
+
+            kek = 
org.apache.xml.security.utils.KeyUtils.aesWrapKeyWithDHGeneratedKey(parameterSpec);
+        } catch (XMLSecurityException ex) {
+            LOG.debug("Error occurred while resolving the Diffie Hellman key: 
" + ex.getMessage());
+            throw new 
WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
+        }
+
+        String cryptoProvider = data.getDecCrypto().getCryptoProvider();
+        Cipher cipher = 
KeyUtils.getCipherInstance(encryptedKeyTransportMethod, cryptoProvider);
+
+        try {
+            cipher.init(Cipher.UNWRAP_MODE, kek);
+            String keyAlgorithm = 
JCEMapper.translateURItoJCEID(encryptedKeyTransportMethod);
+            return cipher.unwrap(encryptedEphemeralKey, keyAlgorithm, 
Cipher.SECRET_KEY).getEncoded();
+        } catch (InvalidKeyException | NoSuchAlgorithmException  ex) {
+            throw new 
WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
+        }
+    }
+
+    /**
+     * if keyInfo element contains AgreementMethod element then check if it is 
supported EC Diffie-Hellman key agreement algorithm
+     *
+     * @param keyInfoChildElement The KeyInfo child element
+     * @return true if AgreementMethod element is present and DH algorithm 
supported and false if AgreementMethod element is not present
+     * @throws WSSecurityException if AgreementMethod element is present but 
DH algorithm is not supported
+     */
+    private boolean isDiffieHellmanKeyWrap(Element keyInfoChildElement) throws 
WSSecurityException {
+        if 
(EncryptionConstants._TAG_AGREEMENTMETHOD.equals(keyInfoChildElement.getLocalName())
+                && 
WSConstants.ENC_NS.equals(keyInfoChildElement.getNamespaceURI())) {
+            String algorithmURI = keyInfoChildElement.getAttributeNS(null, 
"Algorithm");
+            // Only ECDH_ES is supported for AgreementMethod
+            if (!WSConstants.AGREEMENT_METHOD_ECDH_ES.equals(algorithmURI)) {
+                throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM,
+                        "unknownAlgorithm", new Object[]{algorithmURI});
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Parse keyInfo content to AgreementMethod object.
+     *
+     * @param keyInfoChildElement The KeyInfo child element containing 
AgreementMethod data.
+     * @return the {@link AgreementMethod} object.
+     * @throws WSSecurityException if AgreementMethod element is invalid.
+     */
+    private AgreementMethod getAgreementMethodFromElement(Element 
keyInfoChildElement) throws WSSecurityException {
+        try {
+            return new AgreementMethodImpl(keyInfoChildElement);
+        } catch (XMLSecurityException ex) {
+            throw new 
WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
+        }
+    }
+
+    /**
+     * Get the RecipientKeyInfo child element from the AgreementMethod element.
+     *
+     * @param agreementMethod The AgreementMethod element
+     * @return the RecipientKeyInfo child element which contains the 
recipient's public key.
+     * @throws WSSecurityException if the RecipientKeyInfo element can not be 
retrieved.
+     */
+    private Element getRecipientKeyInfoChildElement(AgreementMethod 
agreementMethod) throws WSSecurityException {
+        try {
+            Element receiverKeyInfoElement =  
agreementMethod.getRecipientKeyInfo().getElement();

Review Comment:
   nit: remove extra space after equals



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscr...@ws.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@ws.apache.org
For additional commands, e-mail: dev-h...@ws.apache.org

Reply via email to