From d7214d8b9cee3e0386ddbcd7f2afeb8112057af2 Mon Sep 17 00:00:00 2001 From: Dan Dold Date: Tue, 30 May 2017 08:39:13 +0100 Subject: [PATCH] Replaced string equals with internal method that does not leak time --- .../credential/DefaultPasswordService.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/apache/shiro/authc/credential/DefaultPasswordService.java b/core/src/main/java/org/apache/shiro/authc/credential/DefaultPasswordService.java index d45858e702..26000e6631 100644 --- a/core/src/main/java/org/apache/shiro/authc/credential/DefaultPasswordService.java +++ b/core/src/main/java/org/apache/shiro/authc/credential/DefaultPasswordService.java @@ -94,7 +94,26 @@ public boolean passwordsMatch(Object plaintext, Hash saved) { Hash computed = this.hashService.computeHash(request); - return saved.equals(computed); + return constantEquals(saved.toString(), computed.toString()); + } + + private boolean constantEquals(String savedHash, String computedHash) { + + int result = 0; + boolean equals; + byte [] savedHashByteArray = savedHash.getBytes(); + byte [] computedHashByteArray = computedHash.getBytes(); + + if(savedHashByteArray.length != computedHashByteArray.length){ + return false; + } else { + for(int index = 0; index < savedHashByteArray.length; index++){ + result |= savedHashByteArray[index] ^ computedHashByteArray[index]; + } + equals = (result == 0); + } + + return equals; } protected void checkHashFormatDurability() {