SEC-811: Provide a mechanism to allocate and rebuild cryptographically strong, randomised tokens.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
package org.springframework.security.token;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link DefaultToken}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*
|
||||
*/
|
||||
public class DefaultTokenTests {
|
||||
@Test
|
||||
public void testEquality() {
|
||||
String key = "key";
|
||||
long created = new Date().getTime();
|
||||
String extendedInformation = "extended";
|
||||
|
||||
DefaultToken t1 = new DefaultToken(key, created, extendedInformation);
|
||||
DefaultToken t2 = new DefaultToken(key, created, extendedInformation);
|
||||
Assert.assertEquals(t1, t2);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testRejectsNullExtendedInformation() {
|
||||
String key = "key";
|
||||
long created = new Date().getTime();
|
||||
new DefaultToken(key, created, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualityWithDifferentExtendedInformation3() {
|
||||
String key = "key";
|
||||
long created = new Date().getTime();
|
||||
|
||||
DefaultToken t1 = new DefaultToken(key, created, "length1");
|
||||
DefaultToken t2 = new DefaultToken(key, created, "longerLength2");
|
||||
Assert.assertFalse(t1.equals(t2));
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
|
||||
|
||||
package org.springframework.security.token;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Date;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link KeyBasedPersistenceTokenService}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*
|
||||
*/
|
||||
public class KeyBasedPersistenceTokenServiceTests {
|
||||
|
||||
private KeyBasedPersistenceTokenService getService() {
|
||||
SecureRandomFactoryBean fb = new SecureRandomFactoryBean();
|
||||
KeyBasedPersistenceTokenService service = new KeyBasedPersistenceTokenService();
|
||||
service.setServerSecret("MY:SECRET$$$#");
|
||||
service.setServerInteger(new Integer(454545));
|
||||
try {
|
||||
SecureRandom rnd = (SecureRandom) fb.getObject();
|
||||
service.setSecureRandom(rnd);
|
||||
service.afterPropertiesSet();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationWithSimpleExtendedInformation() {
|
||||
KeyBasedPersistenceTokenService service = getService();
|
||||
Token token = service.allocateToken("Hello world");
|
||||
Token result = service.verifyToken(token.getKey());
|
||||
Assert.assertEquals(token, result);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testOperationWithComplexExtendedInformation() {
|
||||
KeyBasedPersistenceTokenService service = getService();
|
||||
Token token = service.allocateToken("Hello:world:::");
|
||||
Token result = service.verifyToken(token.getKey());
|
||||
Assert.assertEquals(token, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationWithEmptyRandomNumber() {
|
||||
KeyBasedPersistenceTokenService service = getService();
|
||||
service.setPseudoRandomNumberBits(0);
|
||||
Token token = service.allocateToken("Hello:world:::");
|
||||
Token result = service.verifyToken(token.getKey());
|
||||
Assert.assertEquals(token, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationWithNoExtendedInformation() {
|
||||
KeyBasedPersistenceTokenService service = getService();
|
||||
Token token = service.allocateToken("");
|
||||
Token result = service.verifyToken(token.getKey());
|
||||
Assert.assertEquals(token, result);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testOperationWithMissingKey() {
|
||||
KeyBasedPersistenceTokenService service = getService();
|
||||
Token token = new DefaultToken("", new Date().getTime(), "");
|
||||
service.verifyToken(token.getKey());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testOperationWithTamperedKey() {
|
||||
KeyBasedPersistenceTokenService service = getService();
|
||||
Token goodToken = service.allocateToken("");
|
||||
String fake = goodToken.getKey().toUpperCase();
|
||||
Token token = new DefaultToken(fake, new Date().getTime(), "");
|
||||
service.verifyToken(token.getKey());
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package org.springframework.security.token;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
/**
|
||||
* Tests {@link SecureRandomFactoryBean}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*
|
||||
*/
|
||||
public class SecureRandomFactoryBeanTests {
|
||||
@Test
|
||||
public void testObjectType() {
|
||||
SecureRandomFactoryBean factory = new SecureRandomFactoryBean();
|
||||
Assert.assertEquals(SecureRandom.class, factory.getObjectType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsSingleton() {
|
||||
SecureRandomFactoryBean factory = new SecureRandomFactoryBean();
|
||||
Assert.assertFalse(factory.isSingleton());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatesUsingDefaults() throws Exception {
|
||||
SecureRandomFactoryBean factory = new SecureRandomFactoryBean();
|
||||
Object result = factory.getObject();
|
||||
Assert.assertTrue(result instanceof SecureRandom);
|
||||
int rnd = ((SecureRandom)result).nextInt();
|
||||
Assert.assertTrue(rnd != 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatesUsingSeed() throws Exception {
|
||||
SecureRandomFactoryBean factory = new SecureRandomFactoryBean();
|
||||
Resource resource = new ClassPathResource("org/springframework/security/token/SecureRandomFactoryBeanTests.class");
|
||||
Assert.assertNotNull(resource);
|
||||
factory.setSeed(resource);
|
||||
Object result = factory.getObject();
|
||||
Assert.assertTrue(result instanceof SecureRandom);
|
||||
int rnd = ((SecureRandom)result).nextInt();
|
||||
Assert.assertTrue(rnd != 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.springframework.security.util;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
|
||||
/**
|
||||
* Provides SHA512 digest methods.
|
||||
*
|
||||
* <p>
|
||||
* Based on Commons Codec, which does not presently provide SHA512 support.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 2.0.1
|
||||
*
|
||||
*/
|
||||
public abstract class Sha512DigestUtils {
|
||||
/**
|
||||
* Returns a MessageDigest for the given <code>algorithm</code>.
|
||||
*
|
||||
* @param algorithm The MessageDigest algorithm name.
|
||||
* @return An MD5 digest instance.
|
||||
* @throws RuntimeException when a {@link java.security.NoSuchAlgorithmException} is caught,
|
||||
*/
|
||||
static MessageDigest getDigest(String algorithm) {
|
||||
try {
|
||||
return MessageDigest.getInstance(algorithm);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an SHA digest.
|
||||
*
|
||||
* @return An SHA digest instance.
|
||||
* @throws RuntimeException when a {@link java.security.NoSuchAlgorithmException} is caught,
|
||||
*/
|
||||
private static MessageDigest getSha512Digest() {
|
||||
return getDigest("SHA-512");
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the SHA digest and returns the value as a
|
||||
* <code>byte[]</code>.
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return SHA digest
|
||||
*/
|
||||
public static byte[] sha(byte[] data) {
|
||||
return getSha512Digest().digest(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the SHA digest and returns the value as a
|
||||
* <code>byte[]</code>.
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return SHA digest
|
||||
*/
|
||||
public static byte[] sha(String data) {
|
||||
return sha(data.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the SHA digest and returns the value as a hex string.
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return SHA digest as a hex string
|
||||
*/
|
||||
public static String shaHex(byte[] data) {
|
||||
return new String(Hex.encodeHex(sha(data)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the SHA digest and returns the value as a hex string.
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return SHA digest as a hex string
|
||||
*/
|
||||
public static String shaHex(String data) {
|
||||
return new String(Hex.encodeHex(sha(data)));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user