package se.chalmers.gdcn.hashcash;
import org.testng.annotations.Test;
import se.chalmers.gdcn.network.WorkerID;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.math.BigInteger;
import java.security.KeyPairGenerator;
import java.util.BitSet;
import java.util.Random;
/**
* Created by Leif on 2014-03-29.
*/
public class HashCashTest {
private final SecretKey key1, key2;
private final KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
private final HashCash hc;
private final Random random;
public HashCashTest() throws Exception {
KeyGenerator keygen = KeyGenerator.getInstance("HmacSHA256");
key1 = keygen.generateKey();
key2 = keygen.generateKey();
hc = new HashCash(key1,20,22);
random = new Random();
}
@Test
public void testCheckZerosPos() {
int difficulty = random.nextInt(100);
Challenge challenge = hc.generateChallenge(randomString(),difficulty);
BitSet hashBits = new BitSet(difficulty*2);
hashBits.clear();
hashBits.set(difficulty,difficulty*2);
assert challenge.checkZeros(hashBits.toByteArray());
}
@Test
public void testCheckZerosNeg() {
int difficulty = random.nextInt(100);
Challenge challenge = hc.generateChallenge(randomString(),difficulty);
BitSet hashBits = new BitSet(difficulty*2);
hashBits.set(0,difficulty);
assert !challenge.checkZeros(hashBits.toByteArray());
}
@Test
public void testHashLength() {
byte[] seed = new byte[random.nextInt(32)];
byte[] token = new byte[random.nextInt(32)];
random.nextBytes(seed);
random.nextBytes(token);
assert Challenge.hash(seed,token).length == 20;
}
@Test
public void testWrongMAC() throws Exception {
byte[] seed = randomString().getBytes("UTF-8");
Challenge authenticChallenge = new Challenge(seed,1,key1);
byte[] mac = authenticChallenge.getMAC();
Challenge nonAuthenticChallenge = new Challenge(seed,2, mac);
assert !nonAuthenticChallenge.isAuthentic(key1);
}
@Test
public void testWrongSolution() throws Exception {
Challenge challenge = hc.generateChallenge(randomString(), 50);
Solution invalidSolution = new Solution(randomString().getBytes("UTF-8"),challenge);
assert !invalidSolution.isValid(key1);
}
@Test
public void testSolve() throws Exception {
Challenge challenge = hc.generateChallenge(randomString(),20);
assert challenge.solve() != null;
}
@Test
public void testCustomSolution() throws Exception {
Challenge challenge = hc.generateChallenge(randomString(),20);
assert challenge.solve().isValid(key1);
}
@Test
public void testPurposeCustomSolution() throws Exception {
Challenge challenge = hc.generateChallenge(HashCash.Purpose.NONE,randomString(),20);
Solution solution = challenge.solve();
assert solution.isValid(key1) && solution.getPurpose().equals(HashCash.Purpose.NONE);
}
@Test
public void testAuthSolution() throws Exception {
WorkerID jobOwner = randomWorkerID();
WorkerID worker = randomWorkerID();
int score = random.nextInt();
Challenge challenge = hc.generateAuthenticationChallenge(jobOwner, worker, score);
Solution solution = challenge.solve();
assert hc.validateSolution(solution, jobOwner, worker, score);
assert !hc.validateSolution(solution, jobOwner, worker, score+1);
}
@Test
public void testRegSolution() throws Exception {
WorkerID jobOwner = randomWorkerID();
WorkerID worker = randomWorkerID();
int score = random.nextInt();
Challenge challenge = hc.generateRegistrationChallenge(jobOwner, worker, score);
Solution solution = challenge.solve();
assert hc.validateSolution(solution, jobOwner, worker, score);
assert !hc.validateSolution(solution, jobOwner, worker, score+1);
}
@Test
public void testTooEasySolution() throws Exception {
byte[] seed = randomString().getBytes("UTF-8");
Challenge hardChallenge = new Challenge(seed,20, key1);
Challenge easyChallenge = new Challenge(seed,10, key1);
Solution easySolution = easyChallenge.solve();
Solution tooEasySolution = new Solution(easySolution.getToken(),hardChallenge);
assert !tooEasySolution.isValid(key1);
}
@Test
public void testWrongKey() throws Exception {
Challenge challenge = new Challenge(randomString().getBytes("UTF-8"),2, key1);
Solution solution = challenge.solve();
assert !solution.isValid(key2);
}
@Test
public void testReusedSolution() throws Exception {
WorkerChallengesManager wcm = new WorkerChallengesManager();
WorkerID jo = randomWorkerID(), w = randomWorkerID();
Challenge c1 = hc.generateAuthenticationChallenge(jo,w,wcm.getCurrentScore(w));
Solution s1 = c1.solve();
assert hc.validateSolution(s1,jo,w,wcm.getCurrentScore(w));
wcm.solvedChallenge(w,s1);
assert !hc.validateSolution(s1,jo,w,wcm.getCurrentScore(w));
}
private String randomString() {
return new BigInteger(130, random).toString(32);
}
private WorkerID randomWorkerID() {
return new WorkerID(keygen.generateKeyPair().getPublic());
}
}