Skip to content

Commit 4239a9a

Browse files
authored
Create ChaCha20Test.java
1 parent 6f8b350 commit 4239a9a

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package com.thealgorithms.ciphers;
2+
3+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4+
import static org.junit.jupiter.api.Assertions.assertEquals;
5+
import static org.junit.jupiter.api.Assertions.assertThrows;
6+
7+
import org.junit.jupiter.api.Test;
8+
9+
public class ChaCha20Test {
10+
11+
// Test vector from RFC 8439, Section 2.4.2.
12+
private static final byte[] RFC8439_KEY = hexStringToByteArray("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
13+
private static final byte[] RFC8439_NONCE = hexStringToByteArray("000000000000004a00000000"); // Counter = 1, Nonce = 00000000 0000004a 00000000
14+
private static final byte[] RFC8439_PLAINTEXT_64 = hexStringToByteArray(
15+
"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e"
16+
);
17+
private static final byte[] RFC8439_CIPHERTEXT_64 = hexStringToByteArray(
18+
"6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f58375fcd4af034bd16adec164f7a2bda3dc0343a99a46c8b4172421b505877c570b1351d530635359a37e5f1797b596a78c149d5d9963e696f8c792374c4314c67d163f97205463f668f438a0c20a3a7187"
19+
);
20+
21+
// Test vector from RFC 8439, Section 2.4.2 for 114 bytes
22+
private static final byte[] RFC8439_PLAINTEXT_114 = Arrays.copyOf(RFC8439_PLAINTEXT_64, 114);
23+
private static final byte[] RFC8439_CIPHERTEXT_114 = Arrays.copyOf(RFC8439_CIPHERTEXT_64, 114);
24+
25+
@Test
26+
public void testEncryptRFC8439Vector64Bytes() {
27+
byte[] ciphertext = ChaCha20.encrypt(RFC8439_KEY, RFC8439_NONCE, RFC8439_PLAINTEXT_64);
28+
assertArrayEquals(RFC8439_CIPHERTEXT_64, ciphertext);
29+
}
30+
31+
@Test
32+
public void testDecryptRFC8439Vector64Bytes() {
33+
byte[] plaintext = ChaCha20.decrypt(RFC8439_KEY, RFC8439_NONCE, RFC8439_CIPHERTEXT_64);
34+
assertArrayEquals(RFC8439_PLAINTEXT_64, plaintext);
35+
}
36+
37+
@Test
38+
public void testEncryptRFC8439Vector114Bytes() {
39+
// Test encryption with plaintext length not a multiple of 64
40+
byte[] ciphertext = ChaCha20.encrypt(RFC8439_KEY, RFC8439_NONCE, RFC8439_PLAINTEXT_114);
41+
assertArrayEquals(RFC8439_CIPHERTEXT_114, ciphertext);
42+
}
43+
44+
@Test
45+
public void testDecryptRFC8439Vector114Bytes() {
46+
// Test decryption with ciphertext length not a multiple of 64
47+
byte[] plaintext = ChaCha20.decrypt(RFC8439_KEY, RFC8439_NONCE, RFC8439_CIPHERTEXT_114);
48+
assertArrayEquals(RFC8439_PLAINTEXT_114, plaintext);
49+
}
50+
51+
@Test
52+
public void testEncryptDecryptSymmetry() {
53+
byte[] key = new byte[32];
54+
for (int i = 0; i < 32; i++) {
55+
key[i] = (byte) i;
56+
}
57+
byte[] nonce = new byte[12];
58+
for (int i = 0; i < 12; i++) {
59+
nonce[i] = (byte) (i + 100);
60+
}
61+
String originalText = "This is a test message to verify encrypt/decrypt symmetry.";
62+
byte[] plaintext = originalText.getBytes();
63+
64+
byte[] ciphertext = ChaCha20.encrypt(key, nonce, plaintext);
65+
byte[] decryptedText = ChaCha20.decrypt(key, nonce, ciphertext);
66+
67+
assertArrayEquals(plaintext, decryptedText);
68+
assertEquals(originalText, new String(decryptedText));
69+
}
70+
71+
@Test
72+
public void testEmptyPlaintext() {
73+
byte[] empty = new byte[0];
74+
byte[] ciphertext = ChaCha20.encrypt(RFC8439_KEY, RFC8439_NONCE, empty);
75+
assertArrayEquals(empty, ciphertext);
76+
byte[] plaintext = ChaCha20.decrypt(RFC8439_KEY, RFC8439_NONCE, empty);
77+
assertArrayEquals(empty, plaintext);
78+
}
79+
80+
@Test
81+
public void testInvalidKeySize() {
82+
byte[] shortKey = new byte[31];
83+
byte[] longKey = new byte[33];
84+
byte[] nonce = new byte[12];
85+
byte[] data = {1, 2, 3};
86+
87+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.encrypt(shortKey, nonce, data));
88+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.encrypt(longKey, nonce, data));
89+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.decrypt(shortKey, nonce, data));
90+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.decrypt(longKey, nonce, data));
91+
}
92+
93+
@Test
94+
public void testInvalidNonceSize() {
95+
byte[] key = new byte[32];
96+
byte[] shortNonce = new byte[11];
97+
byte[] longNonce = new byte[13];
98+
byte[] data = {1, 2, 3};
99+
100+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.encrypt(key, shortNonce, data));
101+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.encrypt(key, longNonce, data));
102+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.decrypt(key, shortNonce, data));
103+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.decrypt(key, longNonce, data));
104+
}
105+
106+
@Test
107+
public void testNullInputs() {
108+
byte[] key = new byte[32];
109+
byte[] nonce = new byte[12];
110+
byte[] data = {1, 2, 3};
111+
112+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.encrypt(null, nonce, data));
113+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.encrypt(key, null, data));
114+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.encrypt(key, nonce, null));
115+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.decrypt(null, nonce, data));
116+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.decrypt(key, null, data));
117+
assertThrows(IllegalArgumentException.class, () -> ChaCha20.decrypt(key, nonce, null));
118+
}
119+
120+
// Helper to convert hex string to byte array for test vectors
121+
private static byte[] hexStringToByteArray(String s) {
122+
int len = s.length();
123+
if (len % 2 != 0) {
124+
throw new IllegalArgumentException("Hex string must have even length");
125+
}
126+
byte[] data = new byte[len / 2];
127+
for (int i = 0; i < len; i += 2) {
128+
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
129+
}
130+
return data;
131+
}
132+
}

0 commit comments

Comments
 (0)