55import java .util .HexFormat ;
66
77/**
8- * A simple implementation of XOR cipher that, given a key, allows to encrypt and decrypt a plaintext.
8+ * A simple implementation of the XOR cipher that allows both encryption and decryption
9+ * using a given key. This cipher works by applying the XOR bitwise operation between
10+ * the bytes of the input text and the corresponding bytes of the key (repeating the key
11+ * if necessary).
912 *
10- * @author <a href="https://github.com/lcsjunior">lcsjunior</a>
13+ * Usage:
14+ * - Encryption: Converts plaintext into a hexadecimal-encoded ciphertext.
15+ * - Decryption: Converts the hexadecimal ciphertext back into plaintext.
16+ *
17+ * Characteristics:
18+ * - Symmetric: The same key is used for both encryption and decryption.
19+ * - Simple but vulnerable: XOR encryption is insecure for real-world cryptography,
20+ * especially when the same key is reused.
21+ *
22+ * Example:
23+ * Plaintext: "Hello!"
24+ * Key: "key"
25+ * Encrypted: "27090c03120b"
26+ * Decrypted: "Hello!"
1127 *
28+ * Reference: <a href="https://en.wikipedia.org/wiki/XOR_cipher">XOR Cipher - Wikipedia</a>
29+ *
30+ * @author <a href="https://github.com/lcsjunior">lcsjunior</a>
1231 */
1332public final class XORCipher {
1433
34+ // Default character encoding for string conversion
1535 private static final Charset CS_DEFAULT = StandardCharsets .UTF_8 ;
1636
1737 private XORCipher () {
1838 }
1939
40+ /**
41+ * Applies the XOR operation between the input bytes and the key bytes.
42+ * If the key is shorter than the input, it wraps around (cyclically).
43+ *
44+ * @param inputBytes The input byte array (plaintext or ciphertext).
45+ * @param keyBytes The key byte array used for XOR operation.
46+ * @return A new byte array containing the XOR result.
47+ */
2048 public static byte [] xor (final byte [] inputBytes , final byte [] keyBytes ) {
2149 byte [] outputBytes = new byte [inputBytes .length ];
2250 for (int i = 0 ; i < inputBytes .length ; ++i ) {
@@ -25,14 +53,40 @@ public static byte[] xor(final byte[] inputBytes, final byte[] keyBytes) {
2553 return outputBytes ;
2654 }
2755
56+ /**
57+ * Encrypts the given plaintext using the XOR cipher with the specified key.
58+ * The result is a hexadecimal-encoded string representing the ciphertext.
59+ *
60+ * @param plainText The input plaintext to encrypt.
61+ * @param key The encryption key.
62+ * @throws IllegalArgumentException if the key is empty.
63+ * @return A hexadecimal string representing the encrypted text.
64+ */
2865 public static String encrypt (final String plainText , final String key ) {
66+ if (key .isEmpty ()) {
67+ throw new IllegalArgumentException ("Key must not be empty" );
68+ }
69+
2970 byte [] plainTextBytes = plainText .getBytes (CS_DEFAULT );
3071 byte [] keyBytes = key .getBytes (CS_DEFAULT );
3172 byte [] xorResult = xor (plainTextBytes , keyBytes );
3273 return HexFormat .of ().formatHex (xorResult );
3374 }
3475
76+ /**
77+ * Decrypts the given ciphertext (in hexadecimal format) using the XOR cipher
78+ * with the specified key. The result is the original plaintext.
79+ *
80+ * @param cipherText The hexadecimal string representing the encrypted text.
81+ * @param key The decryption key (must be the same as the encryption key).
82+ * @throws IllegalArgumentException if the key is empty.
83+ * @return The decrypted plaintext.
84+ */
3585 public static String decrypt (final String cipherText , final String key ) {
86+ if (key .isEmpty ()) {
87+ throw new IllegalArgumentException ("Key must not be empty" );
88+ }
89+
3690 byte [] cipherBytes = HexFormat .of ().parseHex (cipherText );
3791 byte [] keyBytes = key .getBytes (CS_DEFAULT );
3892 byte [] xorResult = xor (cipherBytes , keyBytes );
0 commit comments