From 2eda3778cee5b66fb0fde97a7bf4a7d9e8ab537a Mon Sep 17 00:00:00 2001 From: Luiz Date: Tue, 1 Oct 2024 00:34:12 -0300 Subject: [PATCH 1/4] Implemented Simple XOR Cipher --- DIRECTORY.md | 2 + .../com/thealgorithms/ciphers/XORCipher.java | 40 +++++++++++++++++++ .../thealgorithms/ciphers/XORCipherTest.java | 20 ++++++++++ 3 files changed, 62 insertions(+) create mode 100644 src/main/java/com/thealgorithms/ciphers/XORCipher.java create mode 100644 src/test/java/com/thealgorithms/ciphers/XORCipherTest.java diff --git a/DIRECTORY.md b/DIRECTORY.md index bbcee88e52be..fb1074340334 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) @@ -613,6 +614,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..de9d92d95214 --- /dev/null +++ b/src/main/java/com/thealgorithms/ciphers/XORCipher.java @@ -0,0 +1,40 @@ +package com.thealgorithms.ciphers; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +/** + * A simple implementation of XOR cipher that, given a key, allows to encrypt and decrypt a plaintext. + * + * @author lcsjunior + * + */ +public class XORCipher { + + private static final Charset CS_DEFAULT = StandardCharsets.UTF_8; + + private XORCipher() { + } + + private 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); + return Base64.getEncoder().encodeToString(xor(plaintextBytes, keyBytes)); + } + + public static String decrypt(final String cipher, final String key) { + byte[] cipherBytes = Base64.getDecoder().decode(cipher); + byte[] keyBytes = key.getBytes(CS_DEFAULT); + return new String(xor(cipherBytes, keyBytes), 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..0d651b0a4d5d --- /dev/null +++ b/src/test/java/com/thealgorithms/ciphers/XORCipherTest.java @@ -0,0 +1,20 @@ +package com.thealgorithms.ciphers; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +class XORCipherTest { + + @Test + void shouldEncryptAndDecryptTest() { + // 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(XORCipher.decrypt(cipherText, key), plaintext); + } + +} From 1f6f98a8600c0650e3336d1699172a51a5e04859 Mon Sep 17 00:00:00 2001 From: Luiz Date: Tue, 1 Oct 2024 00:58:08 -0300 Subject: [PATCH 2/4] fix clang format --- .../com/thealgorithms/ciphers/XORCipher.java | 51 +++++++++---------- .../thealgorithms/ciphers/XORCipherTest.java | 15 +++--- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/thealgorithms/ciphers/XORCipher.java b/src/main/java/com/thealgorithms/ciphers/XORCipher.java index de9d92d95214..d45e9ee4efb7 100644 --- a/src/main/java/com/thealgorithms/ciphers/XORCipher.java +++ b/src/main/java/com/thealgorithms/ciphers/XORCipher.java @@ -8,33 +8,32 @@ * A simple implementation of XOR cipher that, given a key, allows to encrypt and decrypt a plaintext. * * @author lcsjunior - * + * */ public class XORCipher { - private static final Charset CS_DEFAULT = StandardCharsets.UTF_8; - - private XORCipher() { - } - - private 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); - return Base64.getEncoder().encodeToString(xor(plaintextBytes, keyBytes)); - } - - public static String decrypt(final String cipher, final String key) { - byte[] cipherBytes = Base64.getDecoder().decode(cipher); - byte[] keyBytes = key.getBytes(CS_DEFAULT); - return new String(xor(cipherBytes, keyBytes), CS_DEFAULT); - } - + private static final Charset CS_DEFAULT = StandardCharsets.UTF_8; + + private XORCipher() { + } + + private 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); + return Base64.getEncoder().encodeToString(xor(plaintextBytes, keyBytes)); + } + + public static String decrypt(final String cipher, final String key) { + byte[] cipherBytes = Base64.getDecoder().decode(cipher); + byte[] keyBytes = key.getBytes(CS_DEFAULT); + return new String(xor(cipherBytes, keyBytes), CS_DEFAULT); + } } diff --git a/src/test/java/com/thealgorithms/ciphers/XORCipherTest.java b/src/test/java/com/thealgorithms/ciphers/XORCipherTest.java index 0d651b0a4d5d..a13848598d1a 100644 --- a/src/test/java/com/thealgorithms/ciphers/XORCipherTest.java +++ b/src/test/java/com/thealgorithms/ciphers/XORCipherTest.java @@ -8,13 +8,12 @@ class XORCipherTest { @Test void shouldEncryptAndDecryptTest() { - // 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(XORCipher.decrypt(cipherText, key), plaintext); + // 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(XORCipher.decrypt(cipherText, key), plaintext); } - } From 36e1ab01f53590bf2b81417deed95a600f8725d1 Mon Sep 17 00:00:00 2001 From: Luiz Date: Tue, 1 Oct 2024 01:15:37 -0300 Subject: [PATCH 3/4] fix class XORCipher due to build error in pipeline --- src/main/java/com/thealgorithms/ciphers/XORCipher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/ciphers/XORCipher.java b/src/main/java/com/thealgorithms/ciphers/XORCipher.java index d45e9ee4efb7..ca28a59b417e 100644 --- a/src/main/java/com/thealgorithms/ciphers/XORCipher.java +++ b/src/main/java/com/thealgorithms/ciphers/XORCipher.java @@ -10,7 +10,7 @@ * @author lcsjunior * */ -public class XORCipher { +public final class XORCipher { private static final Charset CS_DEFAULT = StandardCharsets.UTF_8; From f2d4ccc26a95b2424aedf209da73a5ec16640c3f Mon Sep 17 00:00:00 2001 From: Luiz Date: Wed, 2 Oct 2024 10:06:04 -0300 Subject: [PATCH 4/4] Added improvements and decrypt test --- .../com/thealgorithms/ciphers/XORCipher.java | 18 ++++++++++-------- .../thealgorithms/ciphers/XORCipherTest.java | 19 +++++++++++++++++-- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/thealgorithms/ciphers/XORCipher.java b/src/main/java/com/thealgorithms/ciphers/XORCipher.java index ca28a59b417e..c4410d8c77ba 100644 --- a/src/main/java/com/thealgorithms/ciphers/XORCipher.java +++ b/src/main/java/com/thealgorithms/ciphers/XORCipher.java @@ -2,7 +2,7 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.util.Base64; +import java.util.HexFormat; /** * A simple implementation of XOR cipher that, given a key, allows to encrypt and decrypt a plaintext. @@ -17,7 +17,7 @@ public final class XORCipher { private XORCipher() { } - private static byte[] xor(final byte[] inputBytes, final byte[] keyBytes) { + 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]); @@ -25,15 +25,17 @@ private static byte[] xor(final byte[] inputBytes, final byte[] keyBytes) { return outputBytes; } - public static String encrypt(final String plaintext, final String key) { - byte[] plaintextBytes = plaintext.getBytes(CS_DEFAULT); + public static String encrypt(final String plainText, final String key) { + byte[] plainTextBytes = plainText.getBytes(CS_DEFAULT); byte[] keyBytes = key.getBytes(CS_DEFAULT); - return Base64.getEncoder().encodeToString(xor(plaintextBytes, keyBytes)); + byte[] xorResult = xor(plainTextBytes, keyBytes); + return HexFormat.of().formatHex(xorResult); } - public static String decrypt(final String cipher, final String key) { - byte[] cipherBytes = Base64.getDecoder().decode(cipher); + public static String decrypt(final String cipherText, final String key) { + byte[] cipherBytes = HexFormat.of().parseHex(cipherText); byte[] keyBytes = key.getBytes(CS_DEFAULT); - return new String(xor(cipherBytes, keyBytes), 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 index a13848598d1a..15e27d5d6778 100644 --- a/src/test/java/com/thealgorithms/ciphers/XORCipherTest.java +++ b/src/test/java/com/thealgorithms/ciphers/XORCipherTest.java @@ -7,13 +7,28 @@ class XORCipherTest { @Test - void shouldEncryptAndDecryptTest() { + 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(XORCipher.decrypt(cipherText, key), plaintext); + assertEquals("My t&xt th@t will be ençrypted...", plainText); } }