diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 9c906c381608..42e8f54eb7fd 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,45 +1,60 @@ -name: "Bug report" -description: "Create a report to help us improve" -title: "[BUG] " +name: Bug Report +description: Report an issue to help us improve +title: "Provide a brief, clear description of the bug" labels: ["bug"] + body: - - type: textarea - id: description + - type: input + id: summary + attributes: + label: Summary + description: Brief description of the issue. + + - type: dropdown + id: environment attributes: - label: "Description" - description: "A clear and concise description of what the bug is." - validations: - required: true + label: Operating System + options: + - Windows + - macOS + - Linux + - Other + - type: textarea id: steps attributes: - label: "Steps to reproduce" - description: "Steps to reproduce the behavior (if applicable)" + label: Steps to Reproduce + description: How can we reproduce this bug? placeholder: | - 1. Go to '...' - 2. Click on '....' - 3. Scroll down to '....' - 4. See error - validations: - required: false + 1. Step one + 2. Step two + + - type: textarea + id: expected + attributes: + label: Expected Behavior + placeholder: What should have happened? + + - type: textarea + id: actual + attributes: + label: Actual Behavior + placeholder: What actually happened? + - type: textarea - id: exceptedbhv + id: logs attributes: - label: "Excepted behavior" - description: "A clear and concise description of what you expected to happen." - validations: - required: true + label: Logs / Error Messages + placeholder: Paste any relevant logs or screenshots. + - type: textarea - id: screenshots + id: config attributes: - label: "Screenshots" - description: "If applicable, add screenshots to help explain your problem." - validations: - required: false + label: Configuration Files + description: VS Code settings.json / other configs if applicable. + - type: textarea id: context attributes: - label: "Additional context" - description: "Is there anything else we should know about this bug report?" - validations: - required: false + label: Additional Context + placeholder: Any other info? diff --git a/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java b/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java new file mode 100644 index 000000000000..66ff2b513b80 --- /dev/null +++ b/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java @@ -0,0 +1,39 @@ +package com.thealgorithms.ciphers; + +import java.security.SecureRandom; +import java.util.Objects; + +public final class OneTimePadCipher { + + private static final SecureRandom RANDOM = new SecureRandom(); + + private OneTimePadCipher() {} + + public static byte[] generateKey(final int length) { + if (length <= 0) { + throw new IllegalArgumentException("Key length must be positive"); + } + byte[] key = new byte[length]; + RANDOM.nextBytes(key); + return key; + } + + public static byte[] encrypt(final byte[] plaintext, final byte[] key) { + Objects.requireNonNull(plaintext, "plaintext"); + Objects.requireNonNull(key, "key"); + + if (plaintext.length != key.length) { + throw new IllegalArgumentException("Plaintext and key must have the same length"); + } + + byte[] ciphertext = new byte[plaintext.length]; + for (int i = 0; i < plaintext.length; i++) { + ciphertext[i] = (byte) (plaintext[i] ^ key[i]); + } + return ciphertext; + } + + public static byte[] decrypt(final byte[] ciphertext, final byte[] key) { + return encrypt(ciphertext, key); + } +} diff --git a/src/test/java/com/thealgorithms/ciphers/OneTimePadCipherTest.java b/src/test/java/com/thealgorithms/ciphers/OneTimePadCipherTest.java new file mode 100644 index 000000000000..e1c11de12690 --- /dev/null +++ b/src/test/java/com/thealgorithms/ciphers/OneTimePadCipherTest.java @@ -0,0 +1,33 @@ +package com.thealgorithms.ciphers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.nio.charset.StandardCharsets; +import org.junit.jupiter.api.Test; + +public class OneTimePadCipherTest { + + @Test + public void encryptDecryptWorks() { + String original = "OTP Test"; + byte[] plaintext = original.getBytes(StandardCharsets.UTF_8); + byte[] key = OneTimePadCipher.generateKey(plaintext.length); + + byte[] encrypted = OneTimePadCipher.encrypt(plaintext, key); + byte[] decrypted = OneTimePadCipher.decrypt(encrypted, key); + + assertEquals(original, new String(decrypted, StandardCharsets.UTF_8)); + } + + @Test + public void throwsIfDifferentLength() { + byte[] plaintext = "Hi".getBytes(StandardCharsets.UTF_8); + byte[] key = new byte[] {1, 2, 3}; + + assertThrows( + IllegalArgumentException.class, + () -> OneTimePadCipher.encrypt(plaintext, key) + ); + } +}