From 571bfc48690b945fcce961c18e5f10f6b0fad5ca Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Tue, 14 Jun 2011 18:34:48 +0100 Subject: [PATCH] Refactoring to use Utf8 encoder instead of String.getBytes("UTF-8"). --- .../encoding/LdapShaPasswordEncoder.java | 4 +--- .../encoding/Md4PasswordEncoder.java | 8 +------ .../MessageDigestPasswordEncoder.java | 8 +------ .../encoding/PasswordEncoderUtils.java | 11 +++++----- .../KeyBasedPersistenceTokenService.java | 22 +++---------------- .../ldap/SpringSecurityLdapTemplateTests.java | 5 +++-- .../security/ldap/LdapUtils.java | 22 ++----------------- .../PasswordComparisonAuthenticator.java | 4 ++-- .../TokenBasedRememberMeServices.java | 12 +++------- 9 files changed, 21 insertions(+), 75 deletions(-) diff --git a/core/src/main/java/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java b/core/src/main/java/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java index fce56502f4..30a79bc006 100644 --- a/core/src/main/java/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java +++ b/core/src/main/java/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java @@ -80,11 +80,9 @@ public class LdapShaPasswordEncoder implements PasswordEncoder { try { sha = MessageDigest.getInstance("SHA"); - sha.update(rawPass.getBytes("UTF-8")); + sha.update(Utf8.encode(rawPass)); } catch (java.security.NoSuchAlgorithmException e) { throw new IllegalStateException("No SHA implementation available!"); - } catch (UnsupportedEncodingException ue) { - throw new IllegalStateException("UTF-8 not supported!"); } if (salt != null) { diff --git a/core/src/main/java/org/springframework/security/authentication/encoding/Md4PasswordEncoder.java b/core/src/main/java/org/springframework/security/authentication/encoding/Md4PasswordEncoder.java index e559ee2071..66c696b8a6 100644 --- a/core/src/main/java/org/springframework/security/authentication/encoding/Md4PasswordEncoder.java +++ b/core/src/main/java/org/springframework/security/authentication/encoding/Md4PasswordEncoder.java @@ -47,13 +47,7 @@ public class Md4PasswordEncoder extends BaseDigestPasswordEncoder { public String encodePassword(String rawPass, Object salt) { String saltedPass = mergePasswordAndSalt(rawPass, salt, false); - byte[] passBytes; - - try { - passBytes = saltedPass.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException("UTF-8 not supported!"); - } + byte[] passBytes = Utf8.encode(saltedPass); Md4 md4 = new Md4(); md4.update(passBytes, 0, passBytes.length); diff --git a/core/src/main/java/org/springframework/security/authentication/encoding/MessageDigestPasswordEncoder.java b/core/src/main/java/org/springframework/security/authentication/encoding/MessageDigestPasswordEncoder.java index af17e25a58..d8f5973288 100644 --- a/core/src/main/java/org/springframework/security/authentication/encoding/MessageDigestPasswordEncoder.java +++ b/core/src/main/java/org/springframework/security/authentication/encoding/MessageDigestPasswordEncoder.java @@ -79,13 +79,7 @@ public class MessageDigestPasswordEncoder extends BaseDigestPasswordEncoder { MessageDigest messageDigest = getMessageDigest(); - byte[] digest; - - try { - digest = messageDigest.digest(saltedPass.getBytes("UTF-8")); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException("UTF-8 not supported!"); - } + byte[] digest = messageDigest.digest(Utf8.encode(saltedPass)); // "stretch" the encoded value if configured to do so for (int i = 1; i < iterations; i++) { diff --git a/core/src/main/java/org/springframework/security/authentication/encoding/PasswordEncoderUtils.java b/core/src/main/java/org/springframework/security/authentication/encoding/PasswordEncoderUtils.java index f821dbf36b..ee6cca91cd 100644 --- a/core/src/main/java/org/springframework/security/authentication/encoding/PasswordEncoderUtils.java +++ b/core/src/main/java/org/springframework/security/authentication/encoding/PasswordEncoderUtils.java @@ -1,5 +1,7 @@ package org.springframework.security.authentication.encoding; +import org.springframework.security.crypto.codec.Utf8; + import java.io.UnsupportedEncodingException; /** @@ -35,11 +37,8 @@ class PasswordEncoderUtils { if(s == null) { return null; } - try { - return s.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException("Could not get bytes in UTF-8 format",e); - } + + return Utf8.encode(s); } private PasswordEncoderUtils() {} -} \ No newline at end of file +} diff --git a/core/src/main/java/org/springframework/security/core/token/KeyBasedPersistenceTokenService.java b/core/src/main/java/org/springframework/security/core/token/KeyBasedPersistenceTokenService.java index 56f7c4fe79..48f6ba3937 100644 --- a/core/src/main/java/org/springframework/security/core/token/KeyBasedPersistenceTokenService.java +++ b/core/src/main/java/org/springframework/security/core/token/KeyBasedPersistenceTokenService.java @@ -1,12 +1,12 @@ package org.springframework.security.core.token; -import java.io.UnsupportedEncodingException; import java.security.SecureRandom; import java.util.Date; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.crypto.codec.Base64; import org.springframework.security.crypto.codec.Hex; +import org.springframework.security.crypto.codec.Utf8; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -68,7 +68,7 @@ public class KeyBasedPersistenceTokenService implements TokenService, Initializi // Compute key String sha512Hex = Sha512DigestUtils.shaHex(content + ":" + serverSecret); String keyPayload = content + ":" + sha512Hex; - String key = convertToString(Base64.encode(convertToBytes(keyPayload))); + String key = Utf8.decode(Base64.encode(Utf8.encode(keyPayload))); return new DefaultToken(key, creationTime, extendedInformation); } @@ -77,7 +77,7 @@ public class KeyBasedPersistenceTokenService implements TokenService, Initializi if (key == null || "".equals(key)) { return null; } - String[] tokens = StringUtils.delimitedListToStringArray(convertToString(Base64.decode(convertToBytes(key))), ":"); + String[] tokens = StringUtils.delimitedListToStringArray(Utf8.decode(Base64.decode(Utf8.encode(key))), ":"); Assert.isTrue(tokens.length >= 4, "Expected 4 or more tokens but found " + tokens.length); long creationTime; @@ -109,22 +109,6 @@ public class KeyBasedPersistenceTokenService implements TokenService, Initializi return new DefaultToken(key, creationTime, extendedInfo.toString()); } - private byte[] convertToBytes(String input) { - try { - return input.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - - private String convertToString(byte[] bytes) { - try { - return new String(bytes, "UTF-8"); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - /** * @return a pseduo random number (hex encoded) */ diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/SpringSecurityLdapTemplateTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/SpringSecurityLdapTemplateTests.java index e6d7521c87..151c0b044e 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/SpringSecurityLdapTemplateTests.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/SpringSecurityLdapTemplateTests.java @@ -28,6 +28,7 @@ import javax.naming.directory.SearchResult; import org.junit.*; import org.springframework.ldap.UncategorizedLdapException; import org.springframework.ldap.core.ContextExecutor; +import org.springframework.security.crypto.codec.Utf8; /** * @author Luke Taylor @@ -51,12 +52,12 @@ public class SpringSecurityLdapTemplateTests extends AbstractLdapIntegrationTest @Test public void compareOfCorrectByteValueSucceeds() { - assertTrue(template.compare("uid=bob,ou=people", "userPassword", LdapUtils.getUtf8Bytes("bobspassword"))); + assertTrue(template.compare("uid=bob,ou=people", "userPassword", Utf8.encode("bobspassword"))); } @Test public void compareOfWrongByteValueFails() { - assertFalse(template.compare("uid=bob,ou=people", "userPassword", LdapUtils.getUtf8Bytes("wrongvalue"))); + assertFalse(template.compare("uid=bob,ou=people", "userPassword", Utf8.encode("wrongvalue"))); } @Test diff --git a/ldap/src/main/java/org/springframework/security/ldap/LdapUtils.java b/ldap/src/main/java/org/springframework/security/ldap/LdapUtils.java index 542bdbe794..4254002308 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/LdapUtils.java +++ b/ldap/src/main/java/org/springframework/security/ldap/LdapUtils.java @@ -17,6 +17,7 @@ package org.springframework.security.ldap; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DistinguishedName; +import org.springframework.security.crypto.codec.Utf8; import org.springframework.util.Assert; import org.apache.commons.logging.Log; @@ -25,7 +26,6 @@ import org.apache.commons.logging.LogFactory; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; -import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; @@ -123,29 +123,11 @@ public final class LdapUtils { return baseDn; } - public static byte[] getUtf8Bytes(String s) { - try { - return s.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - // Should be impossible since UTF-8 is required by all implementations - throw new IllegalStateException("Failed to convert string to UTF-8 bytes. Shouldn't be possible"); - } - } - - public static String getUtf8BytesAsString(byte[] utf8) { - try { - return new String(utf8, "UTF-8"); - } catch (UnsupportedEncodingException e) { - // Should be impossible since UTF-8 is required by all implementations - throw new IllegalStateException("Failed to convert string to UTF-8 bytes. Shouldn't be possible"); - } - } - public static String convertPasswordToString(Object passObj) { Assert.notNull(passObj, "Password object to convert must not be null"); if(passObj instanceof byte[]) { - return getUtf8BytesAsString((byte[])passObj); + return Utf8.decode((byte[])passObj); } else if (passObj instanceof String) { return (String)passObj; } else { diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java index e4faf248c1..9ce5da4695 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java @@ -26,7 +26,7 @@ import org.springframework.security.authentication.encoding.LdapShaPasswordEncod import org.springframework.security.authentication.encoding.PasswordEncoder; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.ldap.LdapUtils; +import org.springframework.security.crypto.codec.Utf8; import org.springframework.security.ldap.SpringSecurityLdapTemplate; import org.springframework.util.Assert; @@ -96,7 +96,7 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic } String encodedPassword = passwordEncoder.encodePassword(password, null); - byte[] passwordBytes = LdapUtils.getUtf8Bytes(encodedPassword); + byte[] passwordBytes = Utf8.encode(encodedPassword); if (!ldapTemplate.compare(user.getDn().toString(), passwordAttributeName, passwordBytes)) { throw new BadCredentialsException(messages.getMessage("PasswordComparisonAuthenticator.badCredentials", diff --git a/web/src/main/java/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.java b/web/src/main/java/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.java index 4e650bb973..750aab297f 100644 --- a/web/src/main/java/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.java +++ b/web/src/main/java/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.java @@ -18,6 +18,7 @@ package org.springframework.security.web.authentication.rememberme; import org.springframework.security.core.Authentication; import org.springframework.security.crypto.codec.Hex; import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.codec.Utf8; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; @@ -222,9 +223,6 @@ public class TokenBasedRememberMeServices extends AbstractRememberMeServices { /** * Constant time comparison to prevent against timing attacks. - * @param expected - * @param actual - * @return */ private static boolean equals(String expected, String actual) { byte[] expectedBytes = bytesUtf8(expected); @@ -241,13 +239,9 @@ public class TokenBasedRememberMeServices extends AbstractRememberMeServices { } private static byte[] bytesUtf8(String s) { - if(s == null) { + if (s == null) { return null; } - try { - return s.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException("Could not get bytes in UTF-8 format",e); - } + return Utf8.encode(s); } }