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


##########
policy/src/main/java/org/apache/wss4j/policy/model/AlgorithmSuite.java:
##########
@@ -220,6 +220,7 @@ public static final class AlgorithmSuiteType {
         private String encryptionDigest;
         private String symmetricSignature = SPConstants.HMAC_SHA1;
         private String asymmetricSignature = SPConstants.RSA_SHA1;
+        private String encryptionKeyAgreementMethod;

Review Comment:
   Is there any proposal to update the WS-SecurityPolicy spec to include key 
agreement methods? Otherwise this is a non-standard addition.



##########
ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncryptedKey.java:
##########
@@ -505,35 +533,61 @@ protected void createEncryptedKeyElement(Key key) throws 
WSSecurityException {
         }
     }
 
-    protected byte[] encryptSymmetricKey(PublicKey encryptingKey, SecretKey 
keyToBeEncrypted)
+    /**
+     * Method builds the KeyAgreementParameterSpec for the ECDH-ES Key 
Agreement Method using
+     * the recipient's public key and preconfigured values: keyEncAlgo, 
digestAlgo and keyAgreementMethod
+     *
+     * @param recipientPublicKey the recipient's public key
+     * @return KeyAgreementParameterSpec the {@link 
java.security.spec.AlgorithmParameterSpec} for generating the
+     * key for encrypting transport key and generating XML elements.
+     *
+     * @throws WSSecurityException if the KeyAgreementParameterSpec cannot be 
created
+     */
+    public KeyAgreementParameters buildKeyAgreementParameter(PublicKey 
recipientPublicKey)
+            throws  WSSecurityException {
+        KeyAgreementParameters dhSpec;
+        try {
+
+            int keyBitLength  = 
org.apache.xml.security.utils.KeyUtils.getAESKeyBitSizeForWrapAlgorithm(keyEncAlgo);
+            KeyDerivationParameters kdf = 
XMLCipherUtil.constructConcatKeyDerivationParameter(keyBitLength, digestAlgo);
+            KeyPair dhKeyPair = 
org.apache.xml.security.utils.KeyUtils.generateEphemeralDHKeyPair(recipientPublicKey,
 null);
+            dhSpec = 
XMLCipherUtil.constructAgreementParameters(keyAgreementMethod,
+                    KeyAgreementParameters.ActorType.ORIGINATOR, kdf, null, 
recipientPublicKey);
+            dhSpec.setOriginatorKeyPair(dhKeyPair);
+        } catch (XMLEncryptionException e) {
+            throw new WSSecurityException(
+                    WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e
+            );
+        }
+        return dhSpec;
+    }
+
+    /**
+     * Method generates the key for encrypting the transport key using the 
KeyAgreementParameterSpec
+     *
+     * @param keyAgreementParameter the {@link KeyAgreementParameters} for 
generating the secret key
+     * @return SecretKey the secret key for encrypting the transport key
+     * @throws WSSecurityException if the secret key cannot be generated
+     */
+    public SecretKey generateEncryptionKey(KeyAgreementParameters 
keyAgreementParameter) throws WSSecurityException {

Review Comment:
   Is there a reason to make it public?



##########
ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncryptedKey.java:
##########
@@ -505,35 +533,61 @@ protected void createEncryptedKeyElement(Key key) throws 
WSSecurityException {
         }
     }
 
-    protected byte[] encryptSymmetricKey(PublicKey encryptingKey, SecretKey 
keyToBeEncrypted)
+    /**
+     * Method builds the KeyAgreementParameterSpec for the ECDH-ES Key 
Agreement Method using
+     * the recipient's public key and preconfigured values: keyEncAlgo, 
digestAlgo and keyAgreementMethod
+     *
+     * @param recipientPublicKey the recipient's public key
+     * @return KeyAgreementParameterSpec the {@link 
java.security.spec.AlgorithmParameterSpec} for generating the
+     * key for encrypting transport key and generating XML elements.
+     *
+     * @throws WSSecurityException if the KeyAgreementParameterSpec cannot be 
created
+     */
+    public KeyAgreementParameters buildKeyAgreementParameter(PublicKey 
recipientPublicKey)
+            throws  WSSecurityException {
+        KeyAgreementParameters dhSpec;
+        try {
+
+            int keyBitLength  = 
org.apache.xml.security.utils.KeyUtils.getAESKeyBitSizeForWrapAlgorithm(keyEncAlgo);

Review Comment:
   Nit: remove extra space before =



##########
ws-security-dom/src/test/java/org/apache/wss4j/dom/message/EncryptionTest.java:
##########
@@ -313,6 +316,67 @@ 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);
+            Files.write(Paths.get("target", "encrypted-"+certAlias+".xml"), 
outputString.getBytes());

Review Comment:
   Is this needed?



##########
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 keInfo element contains AgreementMethod element then check it is 
supported EC Diffie-Hellman key agreement algorithm

Review Comment:
   typo: keInfo



##########
ws-security-common/src/test/resources/wss-ecdh.properties:
##########
@@ -0,0 +1,4 @@
+org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlin

Review Comment:
   Maybe add some instructions for how the keystore was generated here



-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to