- Notifications
You must be signed in to change notification settings - Fork 19.9k
/
Copy pathXORCipher.java
95 lines (86 loc) · 3.57 KB
/
XORCipher.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
packagecom.thealgorithms.ciphers;
importjava.nio.charset.Charset;
importjava.nio.charset.StandardCharsets;
importjava.util.HexFormat;
/**
* A simple implementation of the XOR cipher that allows both encryption and decryption
* using a given key. This cipher works by applying the XOR bitwise operation between
* the bytes of the input text and the corresponding bytes of the key (repeating the key
* if necessary).
*
* Usage:
* - Encryption: Converts plaintext into a hexadecimal-encoded ciphertext.
* - Decryption: Converts the hexadecimal ciphertext back into plaintext.
*
* Characteristics:
* - Symmetric: The same key is used for both encryption and decryption.
* - Simple but vulnerable: XOR encryption is insecure for real-world cryptography,
* especially when the same key is reused.
*
* Example:
* Plaintext: "Hello!"
* Key: "key"
* Encrypted: "27090c03120b"
* Decrypted: "Hello!"
*
* Reference: <a href="https://en.wikipedia.org/wiki/XOR_cipher">XOR Cipher - Wikipedia</a>
*
* @author <a href="https://github.com/lcsjunior">lcsjunior</a>
*/
publicfinalclassXORCipher {
// Default character encoding for string conversion
privatestaticfinalCharsetCS_DEFAULT = StandardCharsets.UTF_8;
privateXORCipher() {
}
/**
* Applies the XOR operation between the input bytes and the key bytes.
* If the key is shorter than the input, it wraps around (cyclically).
*
* @param inputBytes The input byte array (plaintext or ciphertext).
* @param keyBytes The key byte array used for XOR operation.
* @return A new byte array containing the XOR result.
*/
publicstaticbyte[] xor(finalbyte[] inputBytes, finalbyte[] keyBytes) {
byte[] outputBytes = newbyte[inputBytes.length];
for (inti = 0; i < inputBytes.length; ++i) {
outputBytes[i] = (byte) (inputBytes[i] ^ keyBytes[i % keyBytes.length]);
}
returnoutputBytes;
}
/**
* Encrypts the given plaintext using the XOR cipher with the specified key.
* The result is a hexadecimal-encoded string representing the ciphertext.
*
* @param plainText The input plaintext to encrypt.
* @param key The encryption key.
* @throws IllegalArgumentException if the key is empty.
* @return A hexadecimal string representing the encrypted text.
*/
publicstaticStringencrypt(finalStringplainText, finalStringkey) {
if (key.isEmpty()) {
thrownewIllegalArgumentException("Key must not be empty");
}
byte[] plainTextBytes = plainText.getBytes(CS_DEFAULT);
byte[] keyBytes = key.getBytes(CS_DEFAULT);
byte[] xorResult = xor(plainTextBytes, keyBytes);
returnHexFormat.of().formatHex(xorResult);
}
/**
* Decrypts the given ciphertext (in hexadecimal format) using the XOR cipher
* with the specified key. The result is the original plaintext.
*
* @param cipherText The hexadecimal string representing the encrypted text.
* @param key The decryption key (must be the same as the encryption key).
* @throws IllegalArgumentException if the key is empty.
* @return The decrypted plaintext.
*/
publicstaticStringdecrypt(finalStringcipherText, finalStringkey) {
if (key.isEmpty()) {
thrownewIllegalArgumentException("Key must not be empty");
}
byte[] cipherBytes = HexFormat.of().parseHex(cipherText);
byte[] keyBytes = key.getBytes(CS_DEFAULT);
byte[] xorResult = xor(cipherBytes, keyBytes);
returnnewString(xorResult, CS_DEFAULT);
}
}