This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/main by this push:
     new a4b17ea7bd6 compare username token password and digest in constant 
time (#3182)
a4b17ea7bd6 is described below

commit a4b17ea7bd6ef66271c4289b3e03c16795ee7832
Author: Javid Khan <[email protected]>
AuthorDate: Thu Jun 4 16:28:35 2026 +0530

    compare username token password and digest in constant time (#3182)
---
 .../cxf/ws/security/trust/STSStaxTokenValidator.java    | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSStaxTokenValidator.java
 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSStaxTokenValidator.java
index dced3df8729..57d65082602 100644
--- 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSStaxTokenValidator.java
+++ 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSStaxTokenValidator.java
@@ -18,6 +18,9 @@
  */
 package org.apache.cxf.ws.security.trust;
 
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+
 import javax.security.auth.callback.CallbackHandler;
 
 import org.w3c.dom.Document;
@@ -331,7 +334,7 @@ public class STSStaxTokenValidator
         }
 
         String passDigest = UsernameTokenUtil.doPasswordDigest(nonceVal, 
created, pwCb.getPassword());
-        if (!passwordType.getValue().equals(passDigest)) {
+        if (!constantTimeEquals(passwordType.getValue(), passDigest)) {
             throw new 
WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
         }
         passwordType.setValue(pwCb.getPassword());
@@ -359,12 +362,22 @@ public class STSStaxTokenValidator
             throw new 
WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
         }
 
-        if (!passwordType.getValue().equals(pwCb.getPassword())) {
+        if (!constantTimeEquals(passwordType.getValue(), pwCb.getPassword())) {
             throw new 
WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
         }
         passwordType.setValue(pwCb.getPassword());
     }
 
+    // Compare a client-supplied password (or password digest) against the 
expected value without
+    // leaking, through the time taken to fail, how many leading characters 
matched.
+    private static boolean constantTimeEquals(String provided, String 
expected) {
+        if (provided == null || expected == null) {
+            return false;
+        }
+        return MessageDigest.isEqual(provided.getBytes(StandardCharsets.UTF_8),
+                                     
expected.getBytes(StandardCharsets.UTF_8));
+    }
+
     // Convert to DOM to send the token to the STS - it does not copy 
Nonce/Created/Iteration
     // values
     private Element convertToDOM(

Reply via email to