package net.y3n20u.rfc2898;

import static org.junit.Assert.assertArrayEquals;

import net.y3n20u.util.ByteHelper;

import org.junit.Test;

/**
 * test data defined in RFC3962:
 * <pre>   Iteration count = 1
   Pass phrase = "password"
   Salt = "ATHENA.MIT.EDUraeburn"
   128-bit PBKDF2 output:
       cd ed b5 28 1b b2 f8 01 56 5a 11 22 b2 56 35 15
   256-bit PBKDF2 output:
       cd ed b5 28 1b b2 f8 01 56 5a 11 22 b2 56 35 15
       0a d1 f7 a0 4b b9 f3 a3 33 ec c0 e2 e1 f7 08 37
       
   Iteration count = 2
   Pass phrase = "password"
   Salt="ATHENA.MIT.EDUraeburn"
   128-bit PBKDF2 output:
       01 db ee 7f 4a 9e 24 3e 98 8b 62 c7 3c da 93 5d
   256-bit PBKDF2 output:
       01 db ee 7f 4a 9e 24 3e 98 8b 62 c7 3c da 93 5d
       a0 53 78 b9 32 44 ec 8f 48 a9 9e 61 ad 79 9d 86

   Iteration count = 1200
   Pass phrase = "password"
   Salt = "ATHENA.MIT.EDUraeburn"
   128-bit PBKDF2 output:
       5c 08 eb 61 fd f7 1e 4e 4e c3 cf 6b a1 f5 51 2b
       
   Iteration count = 5
   Pass phrase = "password"
   Salt=0x1234567878563412
   128-bit PBKDF2 output:
       d1 da a7 86 15 f2 87 e6 a1 c8 b1 20 d7 06 2a 49
   (This test is based on values given in [PECMS].)

   Iteration count = 1200
   Pass phrase = (64 characters)
     "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
   Salt="pass phrase equals block size"
   128-bit PBKDF2 output:
       13 9c 30 c0 96 6b c3 2b a5 5f db f2 12 53 0a c9
   256-bit PBKDF2 output:
       13 9c 30 c0 96 6b c3 2b a5 5f db f2 12 53 0a c9
       c5 ec 59 f1 a4 52 f5 cc 9a d9 40 fe a0 59 8e d1

   Iteration count = 1200
   Pass phrase = (65 characters)
     "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
   Salt = "pass phrase exceeds block size"
   128-bit PBKDF2 output:
       9c ca d6 d4 68 77 0c d5 1b 10 e6 a6 87 21 be 61
   256-bit PBKDF2 output:
       9c ca d6 d4 68 77 0c d5 1b 10 e6 a6 87 21 be 61
       1a 8b 4d 28 26 01 db 3b 36 be 92 46 91 5e c8 2a

   Iteration count = 50
   Pass phrase = g-clef (0xf09d849e)
   Salt = "EXAMPLE.COMpianist"
   128-bit PBKDF2 output:
       6b 9c f2 6d 45 45 5a 43 a5 b8 bb 27 6a 40 3b 39
   256-bit PBKDF2 output:
       6b 9c f2 6d 45 45 5a 43 a5 b8 bb 27 6a 40 3b 39
       e7 fe 37 a0 c4 1e 02 c2 81 ff 30 69 e1 e9 4f 52
</pre>
 * @author y3n20u@gmail.com
 *
 */
public class Pbkdf2Test {


	/**
	 * Test of deriveKey 1.
	 * <pre>   Iteration count = 1
	   Pass phrase = "password"
	   Salt = "ATHENA.MIT.EDUraeburn"
	   128-bit PBKDF2 output:
	       cd ed b5 28 1b b2 f8 01 56 5a 11 22 b2 56 35 15</pre>
	 */
	@Test
	public void testDeriveKey1() {
		byte[] p = "password".getBytes();
		byte[] s = "ATHENA.MIT.EDUraeburn".getBytes();
		int c = 1;
		int dkLen = 128 / 8;
		
		byte[] expectedResult = ByteHelper.getBytes("cd ed b5 28 1b b2 f8 01 56 5a 11 22 b2 56 35 15");
		
		assertArrayEquals(expectedResult, new Pbkdf2().deriveKey(p, s, c, dkLen));
	}
	
	/**
	 * Test of deriveKey 2.
	 * <pre>   Iteration count = 1
	   Pass phrase = "password"
	   Salt = "ATHENA.MIT.EDUraeburn"
       256-bit PBKDF2 output:
           cd ed b5 28 1b b2 f8 01 56 5a 11 22 b2 56 35 15
           0a d1 f7 a0 4b b9 f3 a3 33 ec c0 e2 e1 f7 08 37</pre>
	 */
	@Test
	public void testDeriveKey2() {
		byte[] p = "password".getBytes();
		byte[] s = "ATHENA.MIT.EDUraeburn".getBytes();
		int c = 1;
		int dkLen = 256 / 8;
		
		byte[] expectedResult = ByteHelper.getBytes("cd ed b5 28 1b b2 f8 01 56 5a 11 22 b2 56 35 15 0a d1 f7 a0 4b b9 f3 a3 33 ec c0 e2 e1 f7 08 37");
		
		assertArrayEquals(expectedResult, new Pbkdf2().deriveKey(p, s, c, dkLen));
	}
	
	/**
	 * Test of deriveKey 3.
     * <pre>   Iteration count = 2
   Pass phrase = "password"
   Salt="ATHENA.MIT.EDUraeburn"
   128-bit PBKDF2 output:
       01 db ee 7f 4a 9e 24 3e 98 8b 62 c7 3c da 93 5d</pre>
	 */
	@Test
	public void testDeriveKey3() {
		byte[] p = "password".getBytes();
		byte[] s = "ATHENA.MIT.EDUraeburn".getBytes();
		int c = 2;
		int dkLen = 128 / 8;
		
		byte[] expectedResult = ByteHelper.getBytes("01 db ee 7f 4a 9e 24 3e 98 8b 62 c7 3c da 93 5d");
		
		assertArrayEquals(expectedResult, new Pbkdf2().deriveKey(p, s, c, dkLen));
	}
	
	/**
	 * Test of deriveKey 4.
	 * <pre>   Iteration count = 2
   Pass phrase = "password"
   Salt="ATHENA.MIT.EDUraeburn"
   256-bit PBKDF2 output:
       01 db ee 7f 4a 9e 24 3e 98 8b 62 c7 3c da 93 5d
       a0 53 78 b9 32 44 ec 8f 48 a9 9e 61 ad 79 9d 86</pre>
	 */
	@Test
	public void testDeriveKey4() {
		byte[] p = "password".getBytes();
		byte[] s = "ATHENA.MIT.EDUraeburn".getBytes();
		int c = 2;
		int dkLen = 256 / 8;
		
		byte[] expectedResult = ByteHelper.getBytes("01 db ee 7f 4a 9e 24 3e 98 8b 62 c7 3c da 93 5d a0 53 78 b9 32 44 ec 8f 48 a9 9e 61 ad 79 9d 86");
		
		assertArrayEquals(expectedResult, new Pbkdf2().deriveKey(p, s, c, dkLen));
	}
	
	/**
	 * Test of deriveKey 5.
	 * <pre>   Iteration count = 1200
   Pass phrase = "password"
   Salt = "ATHENA.MIT.EDUraeburn"
   128-bit PBKDF2 output:
       5c 08 eb 61 fd f7 1e 4e 4e c3 cf 6b a1 f5 51 2b</pre>
	 */
	@Test
	public void testDeriveKey5() {
		byte[] p = "password".getBytes();
		byte[] s = "ATHENA.MIT.EDUraeburn".getBytes();
		int c = 1200;
		int dkLen = 128 / 8;
		
		byte[] expectedResult = ByteHelper.getBytes("5c 08 eb 61 fd f7 1e 4e 4e c3 cf 6b a1 f5 51 2b");
		
		assertArrayEquals(expectedResult, new Pbkdf2().deriveKey(p, s, c, dkLen));
	}

	/**
	 * Test of deriveKey 6.
	 * <pre>   Iteration count = 5
   Pass phrase = "password"
   Salt=0x1234567878563412
   128-bit PBKDF2 output:
       d1 da a7 86 15 f2 87 e6 a1 c8 b1 20 d7 06 2a 49</pre>
	 */
	@Test
	public void testDeriveKey6() {
		byte[] p = "password".getBytes();
		byte[] s = ByteHelper.getBytes("1234567878563412");
		int c = 5;
		int dkLen = 128 / 8;
		
		byte[] expectedResult = ByteHelper.getBytes("d1 da a7 86 15 f2 87 e6 a1 c8 b1 20 d7 06 2a 49");
		
		assertArrayEquals(expectedResult, new Pbkdf2().deriveKey(p, s, c, dkLen));
	}
	
	/**
	 * Test of deriveKey 7.
	 * <pre>	
	   Iteration count = 1200
	   Pass phrase = (64 characters)
	     "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
	   Salt="pass phrase equals block size"
	   128-bit PBKDF2 output:
	       13 9c 30 c0 96 6b c3 2b a5 5f db f2 12 53 0a c9</pre>
	 */
	@Test
	public void testDeriveKey7() {
		byte[] p = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX".getBytes();
		byte[] s = "pass phrase equals block size".getBytes();
		int c = 1200;
		int dkLen = 128 / 8;
		
		byte[] expectedResult = ByteHelper.getBytes("13 9c 30 c0 96 6b c3 2b a5 5f db f2 12 53 0a c9");
		
		assertArrayEquals(expectedResult, new Pbkdf2().deriveKey(p, s, c, dkLen));
	}

	/**
	 * Test of deriveKey 8.
	 * <pre>	
	   Iteration count = 1200
	   Pass phrase = (64 characters)
	     "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
	   Salt="pass phrase equals block size"
	   256-bit PBKDF2 output:
	       13 9c 30 c0 96 6b c3 2b a5 5f db f2 12 53 0a c9
	       c5 ec 59 f1 a4 52 f5 cc 9a d9 40 fe a0 59 8e d1</pre>
	 */
	@Test
	public void testDeriveKey8() {
		byte[] p = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX".getBytes();
		byte[] s = "pass phrase equals block size".getBytes();
		int c = 1200;
		int dkLen = 256 / 8;
		
		byte[] expectedResult = ByteHelper.getBytes("13 9c 30 c0 96 6b c3 2b a5 5f db f2 12 53 0a c9 c5 ec 59 f1 a4 52 f5 cc 9a d9 40 fe a0 59 8e d1");
		
		assertArrayEquals(expectedResult, new Pbkdf2().deriveKey(p, s, c, dkLen));
	}

	/**
	 * Test of deriveKey 9.
	 * <pre>   Iteration count = 1200
   Pass phrase = (65 characters)
     "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
   Salt = "pass phrase exceeds block size"
   128-bit PBKDF2 output:
       9c ca d6 d4 68 77 0c d5 1b 10 e6 a6 87 21 be 61</pre>
	 */
	@Test
	public void testDeriveKey9() {
		byte[] p = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX".getBytes();
		byte[] s = "pass phrase exceeds block size".getBytes();
		int c = 1200;
		int dkLen = 128 / 8;
		
		byte[] expectedResult = ByteHelper.getBytes("9c ca d6 d4 68 77 0c d5 1b 10 e6 a6 87 21 be 61");
		
		assertArrayEquals(expectedResult, new Pbkdf2().deriveKey(p, s, c, dkLen));
	}

	/**
	 * Test of deriveKey 10.
	 * <pre>   Iteration count = 1200
   Pass phrase = (65 characters)
     "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
   Salt = "pass phrase exceeds block size"
   256-bit PBKDF2 output:
       9c ca d6 d4 68 77 0c d5 1b 10 e6 a6 87 21 be 61
       1a 8b 4d 28 26 01 db 3b 36 be 92 46 91 5e c8 2a</pre>
	 */
	@Test
	public void testDeriveKey10() {
		byte[] p = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX".getBytes();
		byte[] s = "pass phrase exceeds block size".getBytes();
		int c = 1200;
		int dkLen = 256 / 8;
		
		byte[] expectedResult = ByteHelper.getBytes("9c ca d6 d4 68 77 0c d5 1b 10 e6 a6 87 21 be 61 1a 8b 4d 28 26 01 db 3b 36 be 92 46 91 5e c8 2a");
		
		assertArrayEquals(expectedResult, new Pbkdf2().deriveKey(p, s, c, dkLen));
	}
	
	/**
	 * Test of deriveKey 11.
	 * <pre>	   Iteration count = 50
	   Pass phrase = g-clef (0xf09d849e)
	   Salt = "EXAMPLE.COMpianist"
	   128-bit PBKDF2 output:
	       6b 9c f2 6d 45 45 5a 43 a5 b8 bb 27 6a 40 3b 39</pre>
	 */
	@Test
	public void testDeriveKey11() {
		byte[] p = ByteHelper.getBytes("f09d849e");
		byte[] s = "EXAMPLE.COMpianist".getBytes();
		int c = 50;
		int dkLen = 128 / 8;
		
		byte[] expectedResult = ByteHelper.getBytes("6b 9c f2 6d 45 45 5a 43 a5 b8 bb 27 6a 40 3b 39");
		
		assertArrayEquals(expectedResult, new Pbkdf2().deriveKey(p, s, c, dkLen));
	}
	
	/**
	 * Test of deriveKey 12.
	 * <pre>	   Iteration count = 50
	   Pass phrase = g-clef (0xf09d849e)
	   Salt = "EXAMPLE.COMpianist"
	   256-bit PBKDF2 output:
	       6b 9c f2 6d 45 45 5a 43 a5 b8 bb 27 6a 40 3b 39
	       e7 fe 37 a0 c4 1e 02 c2 81 ff 30 69 e1 e9 4f 52</pre>
	 */
	@Test
	public void testDeriveKey12() {
		byte[] p = ByteHelper.getBytes("f09d849e");
		byte[] s = "EXAMPLE.COMpianist".getBytes();
		int c = 50;
		int dkLen = 256 / 8;
		
		byte[] expectedResult = ByteHelper.getBytes("6b 9c f2 6d 45 45 5a 43 a5 b8 bb 27 6a 40 3b 39 e7 fe 37 a0 c4 1e 02 c2 81 ff 30 69 e1 e9 4f 52");
		
		assertArrayEquals(expectedResult, new Pbkdf2().deriveKey(p, s, c, dkLen));
	}


}
