The task is somewhat under-specified, especially the third (optional) section so I'm skipping that for now. Each sub-task has it's own code.
Sub-task one: generate one-time-pad files.
This is a fairly basic otp file generator. Uses Crypt::Random for decently high quality random numbers. (Random bytes are drawn from /dev/urandom on Unix-like systems, and CryptGenRandom() on Windows.) It will ask for a file name to save to, and the number of lines you want. Each line can be used to encode up to 48 characters of data. Default is 1000 lines, Only generating 4 lines here for demonstration purposes. Saving the file to 'rosettacode.1tp'.
subMAIN { put "Generate data for one time pad encryption.\n" ~"File will have .1tp extension.";my $fn; loop { $fn = prompt 'Filename for one time pad data: ';if $fn !~~ /'.1tp' $/ { $fn ~= '.1tp' }if $fn.IO.e {my $ow = prompt "$fn aready exists, over-write? y/[n] ";lastif $ow ~~ m:i/'y'/; redo; } last; } put 'Each line will contain 48 characters of encyption data.'; my $lines = prompt 'How many lines of data to generate? [1000] '; $lines ||= 1000; generate($fn, $lines); say "One-time-pad data saved to:", $fn.IO.absolute; sub generate ( $fn, $lines) { use Crypt::Random; $fn.IO.spurt: "# one-time-pad encryption data\n" ~ ((sprintf(" %s %s %s %s %s %s %s %s\n", ((('A'..'Z')[crypt_random_uniform(26)] xx 6).join) xx 8)) xx $lines).join; }}
Output:
Generate data for one time pad encryption.
File wile have .1tp extension.
Filename for one time pad data: rosettacode
Each line will contain 48 characters of encyption data.
How many lines of data to generate? [1000] 4
One-time-pad data saved to: /home/myhome/mydirectory/rosettacode.1tp
Sub-task two: encrypt/decrypt text using the otp files generated by part one.
One-time-pad encryption gets it's security from the fact that the pads are used one time. As a line is used in the otp file, it needs to be marked as used, or removed so it doesn't get reused. Theoretically, you would make a copy of rosettacode.1tp and send it by secure means to the receiver of your encrypted text so that they can use it to decrypt. Since we are encrypting and decrypting on the same computer, we'll make a copy of the otp file named rosettacopy.1tp and use that for decryption so the encrypt and decrypt functions don't conflict.
subs2v ($s) { $s.uc.comb(/ <[ A..Z ]> /)».ord »-» 65 }subv2s (@v) { (@v »%» 26 »+» 65)».chr.join }subhide ($secret, $otp) { v2s(s2v($secret) »+» s2v($otp)) }subreveal ($hidden, $otp) { v2s(s2v($hidden) »-» s2v($otp)) }subotp-data ($fn, $lines) {my $fh = $fn.IO.open :rw;my $data;my $count = 0; repeat {my $pos = $fh.tell;my $line = $fh.get;if $line.substr(0,1) ne'-'|'#' { $data ~= $line; $fh.seek($pos); $fh.put: '-' ~ $line.substr(1); $count++; } } until $count == $lines or $fh.eof; note "Insufficient lines of data remaining in $fn"if $count != $lines; $data;}subotp-size (Str $string) { ceiling $string.uc.comb(/ <[ A..Z ]> /) / 48 }subotp-encrypt ( $secret, $fn ) {my $otp-size = otp-size $secret;my $otp-data = otp-data($fn, $otp-size);my $encrypted = hide $secret, $otp-data;# pad encryted text out to a full line with random text $encrypted ~= ('A'..'Z').roll while $encrypted.chars % 48;join"\n", $encrypted.comb(6).rotor(8, :partial).map: { sprintf"{ join ' ', "%s" xx $_ }", $_ };}subotp-decrypt ( $secret, $fn ) {my $otp-size = otp-size $secret;my $otp-data = otp-data($fn, $otp-size);my $plain-text = reveal $secret, $otp-data;join"\n", $plain-text.comb(6).rotor(8, :partial).map: { sprintf"{ join ' ', "%s" xx $_ }", $_ };}my $otp-encrypt-fn = 'rosettacode.1tp';my $otp-decrypt-fn = 'rosettacopy.1tp';my $secret = "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!";say"Secret:\n$secret\n\nEncrypted:";saymy $encrypted = otp-encrypt $secret, $otp-encrypt-fn;say"\nDecrypted:\n", otp-decrypt $encrypted, $otp-decrypt-fn;
Output:
Secret:
Beware the Jabberwock, my son! The jaws that bite, the claws that catch!
Encrypted:
EWQJFY NBAMZE WLWSFT KVBERP XYDMGZ OPRLAK GBXVTP HZRTUO
IXZHCE CUUORL THOFDI DCXRLG JQICPI ZEREHP RLOEAE PRMVJH
Decrypted:
BEWARE THEJAB BERWOC KMYSON THEJAW STHATB ITETHE CLAWST
HATCAT CHOMLN YOOBJC JEXJWW ETMQCA RROTTY IDLFKT ODHQTE
Contents of rosettacode.1tp after encryption / rosettacopy.1tp after decryption: