1
0
mirror of synced 2026-08-04 09:17:02 +00:00

SEC-811: Provide a mechanism to allocate and rebuild cryptographically strong, randomised tokens.

This commit is contained in:
Ben Alex
2008-05-02 10:38:56 +00:00
parent a599ef5398
commit 7a2e1e13d3
9 changed files with 654 additions and 0 deletions
@@ -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));
}
}
@@ -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());
}
}
@@ -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)));
}
}