One-time pad: Difference between revisions

mNo edit summary
Line 389:
<pre>
Similar (not exactly the same, of course) as the Kotlin sample session.
</pre>
 
=={{header|Java}}==
Implementation supports multiple pads using the control name. <br>
 
Implementation also includes the start and end ASCII characters. One usage shows support for uppercase only, a second usage shows allowing spaces, upper case, and lower case in the input text.
 
<lang java>
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class OneTimePad {
 
public static void main(String[] args) {
String controlName = "AtomicBlonde";
generatePad(controlName, 5, 60, 65, 90);
String text = "IT WAS THE BEST OF TIMES IT WAS THE WORST OF TIMES";
String encrypted = parse(true, controlName, text.replaceAll(" ", ""));
String decrypted = parse(false, controlName, encrypted);
System.out.println("Input text = " + text);
System.out.println("Encrypted text = " + encrypted);
System.out.println("Decrypted text = " + decrypted);
 
controlName = "AtomicBlondeCaseSensitive";
generatePad(controlName, 5, 60, 32, 126);
text = "It was the best of times, it was the worst of times.";
encrypted = parse(true, controlName, text);
decrypted = parse(false, controlName, encrypted);
System.out.println();
System.out.println("Input text = " + text);
System.out.println("Encrypted text = " + encrypted);
System.out.println("Decrypted text = " + decrypted);
}
private static String parse(boolean encryptText, String controlName, String text) {
StringBuilder sb = new StringBuilder();
int minCh = 0;
int maxCh = 0;
Pattern minChPattern = Pattern.compile("^# MIN_CH = ([\\d]+)$");
Pattern maxChPattern = Pattern.compile("^# MAX_CH = ([\\d]+)$");
boolean validated = false;
try (BufferedReader in = new BufferedReader(new FileReader(getFileName(controlName))); ) {
String inLine = null;
while ( (inLine = in.readLine()) != null ) {
Matcher minMatcher = minChPattern.matcher(inLine);
if ( minMatcher.matches() ) {
minCh = Integer.parseInt(minMatcher.group(1));
continue;
}
Matcher maxMatcher = maxChPattern.matcher(inLine);
if ( maxMatcher.matches() ) {
maxCh = Integer.parseInt(maxMatcher.group(1));
continue;
}
if ( ! validated && minCh > 0 && maxCh > 0 ) {
validateText(text, minCh, maxCh);
validated = true;
}
// # is comment. - is used key.
if ( inLine.startsWith("#") || inLine.startsWith("-") ) {
continue;
}
// Have encryption key.
String key = inLine;
if ( encryptText ) {
for ( int i = 0 ; i < text.length(); i++) {
sb.append((char) (((text.charAt(i) - minCh + key.charAt(i) - minCh) % (maxCh - minCh + 1)) + minCh));
}
}
else {
for ( int i = 0 ; i < text.length(); i++) {
int decrypt = text.charAt(i) - key.charAt(i);
if ( decrypt < 0 ) {
decrypt += maxCh - minCh + 1;
}
decrypt += minCh;
sb.append((char) decrypt);
}
}
break;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return sb.toString();
}
 
private static void validateText(String text, int minCh, int maxCh) {
// Validate text is in range
for ( char ch : text.toCharArray() ) {
if ( ch != ' ' && (ch < minCh || ch > maxCh) ) {
throw new IllegalArgumentException("ERROR 103: Invalid text.");
}
}
}
private static String getFileName(String controlName) {
return controlName + ".1tp";
}
private static void generatePad(String controlName, int keys, int keyLength, int minCh, int maxCh) {
Random random = new Random();
try ( BufferedWriter writer = new BufferedWriter(new FileWriter(getFileName(controlName), false)); ) {
writer.write("# Lines starting with '#' are ignored.");
writer.newLine();
writer.write("# Lines starting with '-' are previously used.");
writer.newLine();
writer.write("# MIN_CH = " + minCh);
writer.newLine();
writer.write("# MAX_CH = " + maxCh);
writer.newLine();
for ( int line = 0 ; line < keys ; line++ ) {
StringBuilder sb = new StringBuilder();
for ( int ch = 0 ; ch < keyLength ; ch++ ) {
sb.append((char) (random.nextInt(maxCh - minCh + 1) + minCh));
}
writer.write(sb.toString());
writer.newLine();
}
writer.write("# EOF");
writer.newLine();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
 
}
</lang>
 
{{out}}
Demonstration of job:
<pre>
Input text = IT WAS THE BEST OF TIMES IT WAS THE WORST OF TIMES
Encrypted text = ANFNPULTOZRSUNBACQXBMUVIGNWSRJFFNCBVCNF
Decrypted text = ITWASTHEBESTOFTIMESITWASTHEWORSTOFTIMES
 
Input text = It was the best of times, it was the worst of times.
Encrypted text = jF,2abB`:3f9}@85"Y.k[JyWRNO\(q~0Z-5_P:E_H3Q0U(2>'eWy
Decrypted text = It was the best of times, it was the worst of times.
</pre>
Generated one time pad supporting uppercase only.
<pre>
# Lines starting with '#' are ignored.
# Lines starting with '-' are previously used.
# MIN_CH = 65
# MAX_CH = 90
SUJNXBEPNVZZGIISQMFTTYVQNGSWDSNMZXINQJNEQHFBLCSZFCHJGKDLPQPN
RQMZKUCZQZXQDTKXKSVRCFNZYTGZWCDPPMCHDHORVFWBLXJLWTJRBRGUOYWM
PKEVUUBDOMBSFXVJFWGORCZPBSQOWZEOFFHZARVJWTEUQUAKGTMHFAVZSVOO
DKNEKKCTQITFVSOWKMXAOQKWTUYOUXICSEWYCPGOPWFKHYZXQXOIVQUZWWZB
NQUICNAJLTKDFSPXVBIVUUYUTZNNRNBQQXAGPERXZQNQLHEUXSRNIADKXZCL
# EOF
</pre>
 
Generated one time pad supporting lowercase, uppercase, symbols, and spaces.
<pre>
# Lines starting with '#' are ignored.
# Lines starting with '-' are previously used.
# MIN_CH = 32
# MAX_CH = 126
AQ,: nBkQMfV8LC52r.vq\4cFNeg(y=<Z8LyPBUlT>Q@n(=T9 ckJJt6c59[
A{qjk{}x?vlu5(/I4IrkC0NJS2}?_a xF__;5V& -Nz7qh@7OD}l<u9~xGMZ
6JOW|8cZ<,O:vp*LMwU~5u@AJ5nVG7 x?_zfyY(>QMA|U37Z39B}M-lnI-GB
|Qe1*V^PHo"\M:YQo1Z$}2XUk[,L(<P+RDso>'LE.>#K)I6IvrJ&l}O<~=C^
rx0ubl%t(-tOnCQz_y5k%xlHHi$cvaRCIYD<5nUFWD5Hmd@K2.{/N^>PP.<I
# EOF
</pre>