diff --git a/DIRECTORY.md b/DIRECTORY.md index af5905d00747..a05dc8c07415 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -52,6 +52,7 @@ * [RSA](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/RSA.java) * [SimpleSubCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/SimpleSubCipher.java) * [Vigenere](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/Vigenere.java) + * [XORCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/XORCipher.java) * conversions * [AffineConverter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/AffineConverter.java) * [AnyBaseToAnyBase](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/AnyBaseToAnyBase.java) @@ -619,6 +620,7 @@ * [RSATest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/RSATest.java) * [SimpleSubCipherTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/SimpleSubCipherTest.java) * [VigenereTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/VigenereTest.java) + * [XORCipherTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/XORCipherTest.java) * conversions * [AnyBaseToDecimalTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/AnyBaseToDecimalTest.java) * [BinaryToDecimalTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/BinaryToDecimalTest.java) diff --git a/src/main/java/com/thealgorithms/ciphers/XORCipher.java b/src/main/java/com/thealgorithms/ciphers/XORCipher.java new file mode 100644 index 000000000000..c4410d8c77ba --- /dev/null +++ b/src/main/java/com/thealgorithms/ciphers/XORCipher.java @@ -0,0 +1,41 @@ +package com.thealgorithms.ciphers; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.HexFormat; + +/** + * A simple implementation of XOR cipher that, given a key, allows to encrypt and decrypt a plaintext. + * + * @author lcsjunior + * + */ +public final class XORCipher { + + private static final Charset CS_DEFAULT = StandardCharsets.UTF_8; + + private XORCipher() { + } + + public static byte[] xor(final byte[] inputBytes, final byte[] keyBytes) { + byte[] outputBytes = new byte[inputBytes.length]; + for (int i = 0; i < inputBytes.length; ++i) { + outputBytes[i] = (byte) (inputBytes[i] ^ keyBytes[i % keyBytes.length]); + } + return outputBytes; + } + + public static String encrypt(final String plainText, final String key) { + byte[] plainTextBytes = plainText.getBytes(CS_DEFAULT); + byte[] keyBytes = key.getBytes(CS_DEFAULT); + byte[] xorResult = xor(plainTextBytes, keyBytes); + return HexFormat.of().formatHex(xorResult); + } + + public static String decrypt(final String cipherText, final String key) { + byte[] cipherBytes = HexFormat.of().parseHex(cipherText); + byte[] keyBytes = key.getBytes(CS_DEFAULT); + byte[] xorResult = xor(cipherBytes, keyBytes); + return new String(xorResult, CS_DEFAULT); + } +} diff --git a/src/test/java/com/thealgorithms/ciphers/XORCipherTest.java b/src/test/java/com/thealgorithms/ciphers/XORCipherTest.java new file mode 100644 index 000000000000..15e27d5d6778 --- /dev/null +++ b/src/test/java/com/thealgorithms/ciphers/XORCipherTest.java @@ -0,0 +1,34 @@ +package com.thealgorithms.ciphers; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +class XORCipherTest { + + @Test + void xorEncryptTest() { + // given + String plaintext = "My t&xt th@t will be ençrypted..."; + String key = "My ç&cret key!"; + + // when + String cipherText = XORCipher.encrypt(plaintext, key); + + // then + assertEquals("000000b7815e1752111c601f450e48211500a1c206061ca6d35212150d4429570eed", cipherText); + } + + @Test + void xorDecryptTest() { + // given + String cipherText = "000000b7815e1752111c601f450e48211500a1c206061ca6d35212150d4429570eed"; + String key = "My ç&cret key!"; + + // when + String plainText = XORCipher.decrypt(cipherText, key); + + // then + assertEquals("My t&xt th@t will be ençrypted...", plainText); + } +}