Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8d2cdb2

Browse files
feat: implement One-Time Pad cipher (#6941) (#7096)
* feat: implement One-Time Pad cipher (#6941)* style: format OneTimePadCipher with clang-format
1 parent14c0b08 commit8d2cdb2

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
packagecom.thealgorithms.ciphers;
2+
3+
importjava.security.SecureRandom;
4+
importjava.util.Objects;
5+
6+
/**
7+
* One-Time Pad (OTP) cipher implementation.
8+
*
9+
* <p>The One-Time Pad is information-theoretically secure if:
10+
* <ul>
11+
* <li>The key is truly random.</li>
12+
* <li>The key length is at least as long as the plaintext.</li>
13+
* <li>The key is used only once and kept secret.</li>
14+
* </ul>
15+
*
16+
* <p>This implementation is for <b>educational purposes only</b> and should not be
17+
* used in production systems.
18+
*/
19+
publicfinalclassOneTimePadCipher {
20+
21+
privatestaticfinalSecureRandomRANDOM =newSecureRandom();
22+
23+
privateOneTimePadCipher() {
24+
// utility class
25+
}
26+
27+
/**
28+
* Generates a random key of the given length in bytes.
29+
*
30+
* @param length the length of the key in bytes, must be non-negative
31+
* @return a new random key
32+
* @throws IllegalArgumentException if length is negative
33+
*/
34+
publicstaticbyte[]generateKey(intlength) {
35+
if (length <0) {
36+
thrownewIllegalArgumentException("length must be non-negative");
37+
}
38+
byte[]key =newbyte[length];
39+
RANDOM.nextBytes(key);
40+
returnkey;
41+
}
42+
43+
/**
44+
* Encrypts the given plaintext bytes using the provided key.
45+
* <p>The key length must be exactly the same as the plaintext length.
46+
*
47+
* @param plaintext the plaintext bytes, must not be {@code null}
48+
* @param key the one-time pad key bytes, must not be {@code null}
49+
* @return the ciphertext bytes
50+
* @throws IllegalArgumentException if the key length does not match plaintext length
51+
* @throws NullPointerException if plaintext or key is {@code null}
52+
*/
53+
publicstaticbyte[]encrypt(byte[]plaintext,byte[]key) {
54+
validateInputs(plaintext,key);
55+
returnxor(plaintext,key);
56+
}
57+
58+
/**
59+
* Decrypts the given ciphertext bytes using the provided key.
60+
* <p>For a One-Time Pad, decryption is identical to encryption:
61+
* {@code plaintext = ciphertext XOR key}.
62+
*
63+
* @param ciphertext the ciphertext bytes, must not be {@code null}
64+
* @param key the one-time pad key bytes, must not be {@code null}
65+
* @return the decrypted plaintext bytes
66+
* @throws IllegalArgumentException if the key length does not match ciphertext length
67+
* @throws NullPointerException if ciphertext or key is {@code null}
68+
*/
69+
publicstaticbyte[]decrypt(byte[]ciphertext,byte[]key) {
70+
validateInputs(ciphertext,key);
71+
returnxor(ciphertext,key);
72+
}
73+
74+
privatestaticvoidvalidateInputs(byte[]input,byte[]key) {
75+
Objects.requireNonNull(input,"input must not be null");
76+
Objects.requireNonNull(key,"key must not be null");
77+
if (input.length !=key.length) {
78+
thrownewIllegalArgumentException("Key length must match input length");
79+
}
80+
}
81+
82+
privatestaticbyte[]xor(byte[]data,byte[]key) {
83+
byte[]result =newbyte[data.length];
84+
for (inti =0;i <data.length;i++) {
85+
result[i] = (byte) (data[i] ^key[i]);
86+
}
87+
returnresult;
88+
}
89+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
packagecom.thealgorithms.ciphers;
2+
3+
importstaticorg.junit.jupiter.api.Assertions.assertArrayEquals;
4+
importstaticorg.junit.jupiter.api.Assertions.assertEquals;
5+
importstaticorg.junit.jupiter.api.Assertions.assertThrows;
6+
7+
importjava.nio.charset.StandardCharsets;
8+
importorg.junit.jupiter.api.Test;
9+
10+
classOneTimePadCipherTest {
11+
12+
@Test
13+
voidencryptAndDecryptWithRandomKeyRestoresPlaintext() {
14+
Stringplaintext ="The quick brown fox jumps over the lazy dog.";
15+
byte[]plaintextBytes =plaintext.getBytes(StandardCharsets.UTF_8);
16+
17+
byte[]key =OneTimePadCipher.generateKey(plaintextBytes.length);
18+
19+
byte[]ciphertext =OneTimePadCipher.encrypt(plaintextBytes,key);
20+
byte[]decrypted =OneTimePadCipher.decrypt(ciphertext,key);
21+
22+
assertArrayEquals(plaintextBytes,decrypted);
23+
assertEquals(plaintext,newString(decrypted,StandardCharsets.UTF_8));
24+
}
25+
26+
@Test
27+
voidgenerateKeyWithNegativeLengthThrowsException() {
28+
assertThrows(IllegalArgumentException.class, () ->OneTimePadCipher.generateKey(-1));
29+
}
30+
31+
@Test
32+
voidencryptWithMismatchedKeyLengthThrowsException() {
33+
byte[]data ="hello".getBytes(StandardCharsets.UTF_8);
34+
byte[]shortKey =OneTimePadCipher.generateKey(2);
35+
36+
assertThrows(IllegalArgumentException.class, () ->OneTimePadCipher.encrypt(data,shortKey));
37+
}
38+
39+
@Test
40+
voiddecryptWithMismatchedKeyLengthThrowsException() {
41+
byte[]data ="hello".getBytes(StandardCharsets.UTF_8);
42+
byte[]key =OneTimePadCipher.generateKey(data.length);
43+
byte[]ciphertext =OneTimePadCipher.encrypt(data,key);
44+
45+
byte[]wrongSizedKey =OneTimePadCipher.generateKey(data.length +1);
46+
47+
assertThrows(IllegalArgumentException.class, () ->OneTimePadCipher.decrypt(ciphertext,wrongSizedKey));
48+
}
49+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp