How to resolve the algorithm One-time pad step by step in the Raku programming language
Published on 12 May 2024 09:40 PM
How to resolve the algorithm One-time pad step by step in the Raku programming language
Table of Contents
Problem Statement
Implement a One-time pad, for encrypting and decrypting messages. To keep it simple, we will be using letters only. To support the management of pad-files:
For example, here is the data from Wikipedia:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm One-time pad step by step in the Raku programming language
Source code in the raku programming language
sub MAIN {
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] ";
last if $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;
}
}
sub s2v ($s) { $s.uc.comb(/ <[ A..Z ]> /)».ord »-» 65 }
sub v2s (@v) { (@v »%» 26 »+» 65)».chr.join }
sub hide ($secret, $otp) { v2s(s2v($secret) »+» s2v($otp)) }
sub reveal ($hidden, $otp) { v2s(s2v($hidden) »-» s2v($otp)) }
sub otp-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;
}
sub otp-size (Str $string) { ceiling $string.uc.comb(/ <[ A..Z ]> /) / 48 }
sub otp-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 $_ }", $_ };
}
sub otp-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:";
say my $encrypted = otp-encrypt $secret, $otp-encrypt-fn;
say "\nDecrypted:\n", otp-decrypt $encrypted, $otp-decrypt-fn;
You may also check:How to resolve the algorithm Variables step by step in the Go programming language
You may also check:How to resolve the algorithm Odd word problem step by step in the REXX programming language
You may also check:How to resolve the algorithm Superellipse step by step in the Delphi programming language
You may also check:How to resolve the algorithm Filter step by step in the Seed7 programming language
You may also check:How to resolve the algorithm Steffensen's method step by step in the EasyLang programming language