Repository: TheAlgorithms/Java
Pull request #5490 (2024-10-01 04:07:43)

Added a Simple XOR Cipher
<!--
Thank you for your contribution!
In order to reduce the number of notifications sent to the maintainers, please:
- create your PR as draft, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests,
- make sure that all of the CI checks pass,
- mark your PR as ready for review, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review
-->

<!-- For completed items, change [ ] to [x] -->

I've transcribed one of my simple XOR ciphers that I use into Java with the intention of participating in Hacktoberfest and future contributions. Please consider accepting my code.

This is a simple implementation of the XOR cipher that, given a key, allows you to encrypt and decrypt plaintext.

- [x] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Java/blob/master/CONTRIBUTING.md).
- [x] This pull request is all my own work -- I have not plagiarized it.
- [x] All filenames are in PascalCase.
- [x] All functions and variable names follow Java naming conventions.
- [x] All new algorithms have a URL in their comments that points to Wikipedia or other similar explanations.
- [x] All new code is formatted with `clang-format -i --style=file path/to/your/file.java`

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5490?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 52.32%. Comparing base [(`7a5a9e3`)](https://app.codecov.io/gh/TheAlgorithms/Java/commit/7a5a9e3bda44bdab23c8ace87b4cb67c231a2ea3?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) to head [(`1f6f98a`)](https://app.codecov.io/gh/TheAlgorithms/Java/commit/1f6f98a8600c0650e3336d1699172a51a5e04859?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).

<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff              @@
##             master    #5490      +/-   ##
============================================
+ Coverage     52.29%   52.32%   +0.03%     
- Complexity     3257     3262       +5     
============================================
  Files           525      526       +1     
  Lines         15185    15196      +11     
  Branches       2887     2888       +1     
============================================
+ Hits           7941     7952      +11     
  Misses         6920     6920              
  Partials        324      324              
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5490?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).


Patch:
diff --git a/DIRECTORY.md b/DIRECTORY.md
index af5905d0..a05dc8c0 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 00000000..c4410d8c
--- /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 <a href="https://github.com/lcsjunior">lcsjunior</a>
+ *
+ */
+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);
+    }
+}


Test patch:
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 00000000..15e27d5d
--- /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);
+    }
+}