1
0
mirror of synced 2026-08-05 09:47:05 +00:00

SEC-1666: Use constant time comparison for sensitive data.

Constant time comparison helps to mitigate timing attacks. See the following link for more information

 * http://rdist.root.org/2010/07/19/exploiting-remote-timing-attacks/
 * http://en.wikipedia.org/wiki/Timing_attack for more information.
This commit is contained in:
Rob Winch
2011-01-31 23:00:16 -06:00
parent 6a62b51870
commit 8c08eeb57b
9 changed files with 145 additions and 13 deletions
@@ -21,8 +21,6 @@ import static org.springframework.security.crypto.util.EncodingUtils.hexEncode;
import static org.springframework.security.crypto.util.EncodingUtils.subArray;
import static org.springframework.security.crypto.util.EncodingUtils.utf8Encode;
import java.util.Arrays;
import org.springframework.security.crypto.keygen.BytesKeyGenerator;
import org.springframework.security.crypto.keygen.KeyGenerators;
import org.springframework.security.crypto.util.Digester;
@@ -79,8 +77,21 @@ public final class StandardPasswordEncoder implements PasswordEncoder {
return hexDecode(encodedPassword);
}
/**
* Constant time comparison to prevent against timing attacks.
* @param expected
* @param actual
* @return
*/
private boolean matches(byte[] expected, byte[] actual) {
return Arrays.equals(expected, actual);
}
if (expected.length != actual.length) {
return false;
}
int result = 0;
for (int i = 0; i < expected.length; i++) {
result |= expected[i] ^ actual[i];
}
return result == 0;
}
}
@@ -16,6 +16,12 @@ public class StandardPasswordEncoderTests {
assertTrue(encoder.matches("password", result));
}
@Test
public void matchesLengthChecked() {
String result = encoder.encode("password");
assertFalse(encoder.matches("password", result.substring(0,result.length()-1)));
}
@Test
public void notMatches() {
String result = encoder.encode("password");