File Coverage

blib/lib/Crypt/OTP26.pm
Criterion Covered Total %
statement 52 52 100.0
branch 4 4 100.0
condition n/a
subroutine 13 13 100.0
pod 8 8 100.0
total 77 77 100.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             =head1 NAME
4              
5             Crypt::OTP26 - a classic form of encryption
6              
7             =head1 DESCRIPTION
8              
9             This implements a mod-26 One Time Pad encryption, similar to the sort
10             classically used with pen and paper, as described in
11             L
12              
13             Its primary use is to explore the intriguing situation detailed
14             at L
15              
16             NB: We don't handle the cases of generating or securely transmitting the pads
17             themselves.
18              
19             Also, only lower case alpha (ascii 'a-z') characters are handled.
20             If you are actually encrypting and transmitting useful and valuable data, you
21             should use a proper strong crypto module.
22              
23             And though it's based on the OneTimePad concept, it actually supports the pad
24             being shorter or longer than the encrypted text, in which case it is truncated
25             or repeated as appropriate. So... don't do that!
26              
27             =cut
28              
29             package Crypt::OTP26;
30              
31 2     2   57584 use strict; use warnings;
  2     2   4  
  2         69  
  2         9  
  2         3  
  2         48  
32 2     2   1057 use Data::Dumper;
  2         9593  
  2         218  
33              
34             our $VERSION = 0.03;
35 2     2   14 use constant ORD_A => ord('a');
  2         3  
  2         1063  
36              
37             =head1 METHODS
38              
39             =head2 C
40              
41             my $otp = Crypt::OTP26->new();
42              
43             =cut
44              
45             sub new {
46 1     1 1 12 my $class = shift;
47 1         10 return bless {}, $class;
48             }
49              
50             =head2 C
51              
52             Encrypts an alpha text (a-z) with an alpha pad (a-z), by
53             performing mod26 addition on it.
54              
55             my $encrypted = $otp->crypt( $pad, $text );
56             # though it's commutative, so can be in either order
57              
58             my $encrypted = $otp->crypt( 'aced', 'scam' );
59             # returns 'seep'
60              
61             =cut
62              
63             sub crypt {
64 5     5 1 539 my ($self, $string1, $string2) = @_;
65              
66 5         10 my $stream = $self->mk_stream( $string1, $string2 );
67              
68 5         6 my $new_string = '';
69            
70 5         9 while (my ($char1, $char2) = $stream->()) {
71 24         38 $new_string .= $self->crypt_char( $char1, $char2 );
72             }
73 5         33 return $new_string;
74             }
75              
76             =head2 C
77              
78             Decrpyts a previously encrypted text using mod26 sutraction.
79              
80             my $encrypted = $otp->decrypt( $crypt, $pad );
81             my $encrypted = $otp->decrypt( 'aced', 'seep' );
82             # returns 'scam'
83              
84             =cut
85              
86             sub decrypt {
87 6     6 1 521 my ($self, $string1, $string2) = @_;
88              
89 6         11 my $stream = $self->mk_stream( $string1, $string2 );
90              
91 6         10 my $new_string = '';
92            
93 6         11 while (my ($char1, $char2) = $stream->()) {
94 28         50 $new_string .= $self->decrypt_char( $char2, $char1 );
95             }
96 6         47 return $new_string;
97             }
98              
99             =head2 C
100              
101             Return the mod26 integer value of an ascii character.
102              
103             my $int = $otp->char2int('a');
104             # returns 0
105              
106             =cut
107              
108             sub char2int {
109 113     113 1 112 my $self = shift;
110 113         109 my $char = shift;
111 113         196 return ord(lc $char) - ORD_A;
112             }
113              
114             =head2 C
115              
116             my $char = $otp->int2char( 1 );
117             # returns 'b'
118              
119             Will always return 'a'-'z'
120              
121             =cut
122              
123             sub int2char {
124 59     59 1 652 my $self = shift;
125 59         58 my $int = shift;
126 59         211 return chr( ORD_A + ($int % 26));
127             }
128              
129             =head2 C
130              
131             my $char = $otp->crypt_char( 'a', 's' );
132             # returns 's'
133              
134             Crypts 2 characters by performing mod26 addition on them. Called internally by
135             L above.
136              
137             =cut
138            
139             sub crypt_char {
140 25     25 1 582 my ($self, $char1, $char2) = @_;
141 25         36 my $int1 = $self->char2int( $char1 );
142 25         37 my $int2 = $self->char2int( $char2 );
143 25         27 my $int3 = $int1 + $int2;
144 25         38 return $self->int2char( $int3 );
145             }
146              
147             =head2 C
148              
149             Decrypts the character with the appropriate letter from the pad, by performing
150             mod26 subtraction. Called internally L above.
151              
152             my $char = $otp->decrypt_char( $crypt_char, $pad_char );
153             my $char = $otp->decrypt_char( 't', 's' );
154             # returns 'b'
155              
156             =cut
157              
158             sub decrypt_char {
159 30     30 1 588 my ($self, $crypt_char, $pad_char) = @_;
160 30         46 my $int1 = $self->char2int( $crypt_char );
161 30         51 my $int2 = $self->char2int( $pad_char );
162 30         43 my $int3 = $int1 - $int2;
163 30         45 return $self->int2char( $int3 );
164             }
165              
166             =head2 C
167              
168             Private method for iterating the pad and the string.
169              
170             =cut
171              
172             sub mk_stream {
173 12     12 1 558 my $self = shift;
174 12         16 my ($string1, $string2) = @_;
175              
176             # $string1 is the pad, and will repeat if necessary
177              
178 12         39 my @stream1 = split '', $string1;
179 12         33 my @stream2 = split '', $string2;
180              
181             return sub {
182 69 100   69   3212 return unless @stream2;
183 57 100       143 @stream1 = split '', $string1 unless @stream1;
184 57         76 my $char1 = splice(@stream1, 0, 1);
185 57         68 my $char2 = splice(@stream2, 0, 1);
186 57         173 return ($char1, $char2);
187             }
188 12         57 }
189              
190             =head1 AUTHOR
191              
192             (C) 2009
193             osfameron@cpan.org
194              
195             May be distributed under the same conditions as Perl itself
196              
197             Repo is at L
198              
199             (Clone url: git://github.com/osfameron/crypt-otp26.git )
200              
201             =cut
202              
203             1;
204