This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch 2_2_x-fixes
in repository https://gitbox.apache.org/repos/asf/ws-wss4j.git
The following commit(s) were added to refs/heads/2_2_x-fixes by this push:
new cc11b9b WSS-677 - Switch to using MessageDigest.isEqual() to compare
passwords
cc11b9b is described below
commit cc11b9bd912b6d2640309e39247eb06930c84676
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Tue Aug 18 11:34:02 2020 +0100
WSS-677 - Switch to using MessageDigest.isEqual() to compare passwords
---
.../apache/wss4j/dom/message/token/UsernameToken.java | 11 +++++++----
.../wss4j/dom/validate/UsernameTokenValidator.java | 16 +++++++++++-----
.../main/java/org/apache/wss4j/stax/utils/WSSUtils.java | 7 ++++++-
.../wss4j/stax/validate/UsernameTokenValidatorImpl.java | 13 ++++++++++---
4 files changed, 34 insertions(+), 13 deletions(-)
diff --git
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/UsernameToken.java
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/UsernameToken.java
index 7c0bb0d..9d33f2f 100644
---
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/UsernameToken.java
+++
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/token/UsernameToken.java
@@ -565,7 +565,11 @@ public class UsernameToken {
}
public static String doPasswordDigest(String nonce, String created, byte[]
password) {
- String passwdDigest = null;
+ byte[] digestBytes = doRawPasswordDigest(nonce, created, password);
+ return digestBytes != null ?
org.apache.xml.security.utils.XMLUtils.encodeToString(digestBytes) : null;
+ }
+
+ public static byte[] doRawPasswordDigest(String nonce, String created,
byte[] password) {
try {
byte[] b1 = nonce != null ?
org.apache.xml.security.utils.XMLUtils.decode(nonce) : new byte[0];
byte[] b2 = created != null ?
created.getBytes(StandardCharsets.UTF_8) : new byte[0];
@@ -580,12 +584,11 @@ public class UsernameToken {
System.arraycopy(b3, 0, b4, offset, b3.length);
- byte[] digestBytes = KeyUtils.generateDigest(b4);
- passwdDigest =
org.apache.xml.security.utils.XMLUtils.encodeToString(digestBytes);
+ return KeyUtils.generateDigest(b4);
} catch (Exception e) {
LOG.debug(e.getMessage(), e);
}
- return passwdDigest;
+ return null;
}
public static String doPasswordDigest(String nonce, String created, String
password) {
diff --git
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/UsernameTokenValidator.java
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/UsernameTokenValidator.java
index fd1320d..6ea8467 100644
---
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/UsernameTokenValidator.java
+++
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/UsernameTokenValidator.java
@@ -20,6 +20,8 @@
package org.apache.wss4j.dom.validate;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
@@ -165,18 +167,22 @@ public class UsernameTokenValidator implements Validator {
throw new
WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
if (usernameToken.isHashed()) {
- String passDigest;
+ byte[] decodedPassword = XMLUtils.decode(password);
+ byte[] passDigest;
if (passwordsAreEncoded) {
- passDigest = UsernameToken.doPasswordDigest(nonce, createdTime,
+ passDigest = UsernameToken.doRawPasswordDigest(nonce,
createdTime,
XMLUtils.decode(origPassword));
} else {
- passDigest = UsernameToken.doPasswordDigest(nonce,
createdTime, origPassword);
+ passDigest = UsernameToken.doRawPasswordDigest(nonce,
createdTime,
+ origPassword.getBytes(StandardCharsets.UTF_8));
}
- if (!passDigest.equals(password)) {
+ if (!MessageDigest.isEqual(decodedPassword, passDigest)) {
throw new
WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
} else {
- if (!origPassword.equals(password)) {
+ byte[] origPasswordBytes =
origPassword.getBytes(StandardCharsets.UTF_8);
+ byte[] passwordBytes = password.getBytes(StandardCharsets.UTF_8);
+ if (!MessageDigest.isEqual(origPasswordBytes, passwordBytes)) {
throw new
WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
}
diff --git
a/ws-security-stax/src/main/java/org/apache/wss4j/stax/utils/WSSUtils.java
b/ws-security-stax/src/main/java/org/apache/wss4j/stax/utils/WSSUtils.java
index 67e26d6..0213b5a 100644
--- a/ws-security-stax/src/main/java/org/apache/wss4j/stax/utils/WSSUtils.java
+++ b/ws-security-stax/src/main/java/org/apache/wss4j/stax/utils/WSSUtils.java
@@ -114,6 +114,11 @@ public class WSSUtils extends XMLSecurityUtils {
}
public static String doPasswordDigest(byte[] nonce, String created, String
password) throws WSSecurityException {
+ byte[] digest = doRawPasswordDigest(nonce, created, password);
+ return XMLUtils.encodeToString(digest);
+ }
+
+ public static byte[] doRawPasswordDigest(byte[] nonce, String created,
String password) throws WSSecurityException {
try {
byte[] b1 = nonce != null ? nonce : new byte[0];
byte[] b2 = created != null ?
created.getBytes(StandardCharsets.UTF_8) : new byte[0];
@@ -131,7 +136,7 @@ public class WSSUtils extends XMLSecurityUtils {
MessageDigest sha = MessageDigest.getInstance("SHA-1");
sha.reset();
sha.update(b4);
- return XMLUtils.encodeToString(sha.digest());
+ return sha.digest();
} catch (NoSuchAlgorithmException e) {
throw new
WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e,
"decoding.general");
}
diff --git
a/ws-security-stax/src/main/java/org/apache/wss4j/stax/validate/UsernameTokenValidatorImpl.java
b/ws-security-stax/src/main/java/org/apache/wss4j/stax/validate/UsernameTokenValidatorImpl.java
index f72609f..acf9e1b 100644
---
a/ws-security-stax/src/main/java/org/apache/wss4j/stax/validate/UsernameTokenValidatorImpl.java
+++
b/ws-security-stax/src/main/java/org/apache/wss4j/stax/validate/UsernameTokenValidatorImpl.java
@@ -18,6 +18,9 @@
*/
package org.apache.wss4j.stax.validate;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+
import org.apache.wss4j.binding.wss10.AttributedString;
import org.apache.wss4j.binding.wss10.EncodedString;
import org.apache.wss4j.binding.wss10.PasswordString;
@@ -179,8 +182,10 @@ public class UsernameTokenValidatorImpl implements
UsernameTokenValidator {
throw new
WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
- String passDigest = WSSUtils.doPasswordDigest(nonceVal, created,
pwCb.getPassword());
- if (!passwordType.getValue().equals(passDigest)) {
+
+ byte[] passDigest = WSSUtils.doRawPasswordDigest(nonceVal, created,
pwCb.getPassword());
+ byte[] decodedPassword = XMLUtils.decode(passwordType.getValue());
+ if (!MessageDigest.isEqual(decodedPassword, passDigest)) {
throw new
WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
passwordType.setValue(pwCb.getPassword());
@@ -208,7 +213,9 @@ public class UsernameTokenValidatorImpl implements
UsernameTokenValidator {
throw new
WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
- if (!passwordType.getValue().equals(pwCb.getPassword())) {
+ byte[] origPasswordBytes =
pwCb.getPassword().getBytes(StandardCharsets.UTF_8);
+ byte[] passwordBytes =
passwordType.getValue().getBytes(StandardCharsets.UTF_8);
+ if (!MessageDigest.isEqual(origPasswordBytes, passwordBytes)) {
throw new
WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
passwordType.setValue(pwCb.getPassword());