mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-01 09:42:13 +00:00
parent
cd54808718
commit
4b0fb19fff
@ -14,6 +14,8 @@
|
|||||||
package org.springframework.security.crypto.bcrypt;
|
package org.springframework.security.crypto.bcrypt;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
@ -912,17 +914,6 @@ public class BCrypt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static boolean equalsNoEarlyReturn(String a, String b) {
|
static boolean equalsNoEarlyReturn(String a, String b) {
|
||||||
char[] caa = a.toCharArray();
|
return MessageDigest.isEqual(a.getBytes(StandardCharsets.UTF_8), b.getBytes(StandardCharsets.UTF_8));
|
||||||
char[] cab = b.toCharArray();
|
|
||||||
|
|
||||||
if (caa.length != cab.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte ret = 0;
|
|
||||||
for (int i = 0; i < caa.length; i++) {
|
|
||||||
ret |= caa[i] ^ cab[i];
|
|
||||||
}
|
|
||||||
return ret == 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ import org.springframework.security.crypto.codec.Hex;
|
|||||||
import org.springframework.security.crypto.keygen.BytesKeyGenerator;
|
import org.springframework.security.crypto.keygen.BytesKeyGenerator;
|
||||||
import org.springframework.security.crypto.keygen.KeyGenerators;
|
import org.springframework.security.crypto.keygen.KeyGenerators;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
import static org.springframework.security.crypto.util.EncodingUtils.concatenate;
|
import static org.springframework.security.crypto.util.EncodingUtils.concatenate;
|
||||||
import static org.springframework.security.crypto.util.EncodingUtils.subArray;
|
import static org.springframework.security.crypto.util.EncodingUtils.subArray;
|
||||||
|
|
||||||
@ -59,14 +61,6 @@ public abstract class AbstractPasswordEncoder implements PasswordEncoder {
|
|||||||
* Constant time comparison to prevent against timing attacks.
|
* Constant time comparison to prevent against timing attacks.
|
||||||
*/
|
*/
|
||||||
protected static boolean matches(byte[] expected, byte[] actual) {
|
protected static boolean matches(byte[] expected, byte[] actual) {
|
||||||
if (expected.length != actual.length) {
|
return MessageDigest.isEqual(expected, actual);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int result = 0;
|
|
||||||
for (int i = 0; i < expected.length; i++) {
|
|
||||||
result |= expected[i] ^ actual[i];
|
|
||||||
}
|
|
||||||
return result == 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@ package org.springframework.security.crypto.password;
|
|||||||
|
|
||||||
import org.springframework.security.crypto.codec.Utf8;
|
import org.springframework.security.crypto.codec.Utf8;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility for constant time comparison to prevent against timing attacks.
|
* Utility for constant time comparison to prevent against timing attacks.
|
||||||
*
|
*
|
||||||
@ -33,16 +35,8 @@ class PasswordEncoderUtils {
|
|||||||
static boolean equals(String expected, String actual) {
|
static boolean equals(String expected, String actual) {
|
||||||
byte[] expectedBytes = bytesUtf8(expected);
|
byte[] expectedBytes = bytesUtf8(expected);
|
||||||
byte[] actualBytes = bytesUtf8(actual);
|
byte[] actualBytes = bytesUtf8(actual);
|
||||||
int expectedLength = expectedBytes == null ? -1 : expectedBytes.length;
|
|
||||||
int actualLength = actualBytes == null ? -1 : actualBytes.length;
|
|
||||||
|
|
||||||
int result = expectedLength == actualLength ? 0 : 1;
|
return MessageDigest.isEqual(expectedBytes, actualBytes);
|
||||||
for (int i = 0; i < actualLength; i++) {
|
|
||||||
byte expectedByte = expectedLength <= 0 ? 0 : expectedBytes[i % expectedLength];
|
|
||||||
byte actualByte = actualBytes[i % actualLength];
|
|
||||||
result |= expectedByte ^ actualByte;
|
|
||||||
}
|
|
||||||
return result == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] bytesUtf8(String s) {
|
private static byte[] bytesUtf8(String s) {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package org.springframework.security.crypto.password;
|
package org.springframework.security.crypto.password;
|
||||||
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
@ -141,22 +142,7 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
|
|||||||
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
||||||
byte[] digested = decode(encodedPassword);
|
byte[] digested = decode(encodedPassword);
|
||||||
byte[] salt = subArray(digested, 0, this.saltGenerator.getKeyLength());
|
byte[] salt = subArray(digested, 0, this.saltGenerator.getKeyLength());
|
||||||
return matches(digested, encode(rawPassword, salt));
|
return MessageDigest.isEqual(digested, encode(rawPassword, salt));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constant time comparison to prevent against timing attacks.
|
|
||||||
*/
|
|
||||||
private static boolean matches(byte[] expected, byte[] 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] decode(String encodedBytes) {
|
private byte[] decode(String encodedBytes) {
|
||||||
|
@ -23,6 +23,8 @@ import org.springframework.security.crypto.codec.Utf8;
|
|||||||
import org.springframework.security.crypto.keygen.BytesKeyGenerator;
|
import org.springframework.security.crypto.keygen.BytesKeyGenerator;
|
||||||
import org.springframework.security.crypto.keygen.KeyGenerators;
|
import org.springframework.security.crypto.keygen.KeyGenerators;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This {@link PasswordEncoder} is provided for legacy purposes only and is not considered
|
* This {@link PasswordEncoder} is provided for legacy purposes only and is not considered
|
||||||
* secure.
|
* secure.
|
||||||
@ -79,7 +81,7 @@ public final class StandardPasswordEncoder implements PasswordEncoder {
|
|||||||
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
||||||
byte[] digested = decode(encodedPassword);
|
byte[] digested = decode(encodedPassword);
|
||||||
byte[] salt = subArray(digested, 0, saltGenerator.getKeyLength());
|
byte[] salt = subArray(digested, 0, saltGenerator.getKeyLength());
|
||||||
return matches(digested, digest(rawPassword, salt));
|
return MessageDigest.isEqual(digested, digest(rawPassword, salt));
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal helpers
|
// internal helpers
|
||||||
@ -105,21 +107,6 @@ public final class StandardPasswordEncoder implements PasswordEncoder {
|
|||||||
return Hex.decode(encodedPassword);
|
return Hex.decode(encodedPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Constant time comparison to prevent against timing attacks.
|
|
||||||
*/
|
|
||||||
private boolean matches(byte[] expected, byte[] 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int DEFAULT_ITERATIONS = 1024;
|
private static final int DEFAULT_ITERATIONS = 1024;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.security.crypto.scrypt;
|
package org.springframework.security.crypto.scrypt;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
@ -152,15 +153,7 @@ public class SCryptPasswordEncoder implements PasswordEncoder {
|
|||||||
byte[] generated = SCrypt.generate(Utf8.encode(rawPassword), salt, cpuCost, memoryCost, parallelization,
|
byte[] generated = SCrypt.generate(Utf8.encode(rawPassword), salt, cpuCost, memoryCost, parallelization,
|
||||||
keyLength);
|
keyLength);
|
||||||
|
|
||||||
if (derived.length != generated.length) {
|
return MessageDigest.isEqual(derived, generated);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int result = 0;
|
|
||||||
for (int i = 0; i < derived.length; i++) {
|
|
||||||
result |= derived[i] ^ generated[i];
|
|
||||||
}
|
|
||||||
return result == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String digest(CharSequence rawPassword, byte[] salt) {
|
private String digest(CharSequence rawPassword, byte[] salt) {
|
||||||
|
@ -256,15 +256,8 @@ public class TokenBasedRememberMeServices extends AbstractRememberMeServices {
|
|||||||
private static boolean equals(String expected, String actual) {
|
private static boolean equals(String expected, String actual) {
|
||||||
byte[] expectedBytes = bytesUtf8(expected);
|
byte[] expectedBytes = bytesUtf8(expected);
|
||||||
byte[] actualBytes = bytesUtf8(actual);
|
byte[] actualBytes = bytesUtf8(actual);
|
||||||
if (expectedBytes.length != actualBytes.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int result = 0;
|
return MessageDigest.isEqual(expectedBytes, actualBytes);
|
||||||
for (int i = 0; i < expectedBytes.length; i++) {
|
|
||||||
result |= expectedBytes[i] ^ actualBytes[i];
|
|
||||||
}
|
|
||||||
return result == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] bytesUtf8(String s) {
|
private static byte[] bytesUtf8(String s) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user