line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
############################################################################### |
2
|
|
|
|
|
|
|
# Purpose : Substitution cipher based on a keyword alphabet |
3
|
|
|
|
|
|
|
# Author : John Alden |
4
|
|
|
|
|
|
|
# Created : Jan 2005 |
5
|
|
|
|
|
|
|
# CVS : $Id: KeywordAlphabet.pm,v 1.5 2005/03/20 20:02:11 aldenj20 Exp $ |
6
|
|
|
|
|
|
|
############################################################################### |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
package Text::Cipher::KeywordAlphabet; |
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
888
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
35
|
|
11
|
1
|
|
|
1
|
|
771
|
use Text::Cipher; |
|
1
|
|
|
|
|
2760
|
|
|
1
|
|
|
|
|
37
|
|
12
|
1
|
|
|
1
|
|
22
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
72
|
|
13
|
1
|
|
|
1
|
|
6
|
use vars qw($VERSION $AUTOLOAD); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
775
|
|
14
|
|
|
|
|
|
|
$VERSION = sprintf "%d.%03d", (q$Revision: 1.5 $ =~ /: (\d+)\.(\d+)/); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub new { |
17
|
7
|
|
|
7
|
1
|
11089
|
my ($class, $keywords, $offset) = @_; |
18
|
7
|
100
|
|
|
|
203
|
croak("offset must be an integer") unless($offset =~ /^\-?\d*$/); #Integer or blank |
19
|
6
|
|
|
|
|
8
|
my %seen; |
20
|
6
|
100
|
|
|
|
26
|
my $alphabet = join("", map {uc} grep {/^[a-z]$/i && !$seen{$_}++} (split //, $keywords), 'a'..'z'); |
|
156
|
|
|
|
|
231
|
|
|
186
|
|
|
|
|
1031
|
|
21
|
6
|
|
|
|
|
39
|
$alphabet = _rotate_alphabet($alphabet, $offset); |
22
|
6
|
|
|
|
|
33
|
my $self = { |
23
|
6
|
|
|
|
|
862
|
cipher => new Text::Cipher(join("", 'A'..'Z', 'a'..'z'), join("", $alphabet, map {lc} $alphabet)), |
24
|
6
|
|
|
|
|
29
|
decipher => new Text::Cipher(join("", $alphabet, map {lc} $alphabet), join("", 'A'..'Z', 'a'..'z')), |
25
|
|
|
|
|
|
|
alphabet => $alphabet |
26
|
|
|
|
|
|
|
}; |
27
|
6
|
|
|
|
|
574
|
return bless($self, $class); |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub alphabet { |
31
|
6
|
|
|
6
|
1
|
2029
|
my ($self) = shift; |
32
|
6
|
|
|
|
|
49
|
return $self->{alphabet}; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub AUTOLOAD { |
36
|
2
|
|
|
2
|
|
1483
|
my ($self) = shift; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# DESTROY messages should never be propagated |
39
|
2
|
50
|
|
|
|
8
|
return if $AUTOLOAD =~ /::DESTROY$/; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# Remove the package name |
42
|
2
|
|
|
|
|
4
|
my $package = __PACKAGE__; |
43
|
2
|
|
|
|
|
33
|
$AUTOLOAD =~ s/^${package}:://; |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# Pass on to either the enciphering or deciphering object |
46
|
2
|
100
|
|
|
|
7
|
if($AUTOLOAD =~ /^decipher/) { |
47
|
1
|
|
|
|
|
3
|
$AUTOLOAD =~ s/^decipher/encipher/; |
48
|
1
|
|
|
|
|
5
|
$self->{decipher}->$AUTOLOAD(@_); |
49
|
|
|
|
|
|
|
} else { |
50
|
1
|
|
|
|
|
7
|
$self->{cipher}->$AUTOLOAD(@_); |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# Based on routine in Text::Shift |
55
|
|
|
|
|
|
|
sub _rotate_alphabet { |
56
|
|
|
|
|
|
|
# Get parameters |
57
|
6
|
|
|
6
|
|
10
|
my($string,$mag) = @_; |
58
|
6
|
|
|
|
|
10
|
my $strlng = length($string); |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# Handle outliers |
61
|
6
|
100
|
100
|
|
|
41
|
$mag %= $strlng if(abs($mag) > $strlng or $mag < 0); |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# Return rotated string |
64
|
6
|
100
|
|
|
|
17
|
return $string if($mag == 0); |
65
|
4
|
|
|
|
|
12
|
$string .= substr($string,0,$mag, ""); |
66
|
4
|
|
|
|
|
8
|
return $string; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
1; |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=head1 NAME |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
Text::Cipher::KeywordAlphabet - Substitution cipher based on a keyword alphabet |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=head1 SYNOPSIS |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
#Create a keyword alphabet with a left shift of 5 |
78
|
|
|
|
|
|
|
$cipher = new Text::Cipher::KeywordAlphabet("the quick brown fox", -5); |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
#Fetch the generated alphabet |
81
|
|
|
|
|
|
|
$keyword_alphabet = $cipher->alphabet(); |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
#Encipher a string |
84
|
|
|
|
|
|
|
$ciphered = $cipher->encipher($message); |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
#Decipher an enciphered message |
87
|
|
|
|
|
|
|
$message = $cipher->decipher($ciphered); |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
#Some convenience methods |
90
|
|
|
|
|
|
|
$cipher->encipher_scalar(\$some_scalar); |
91
|
|
|
|
|
|
|
$cipher->decipher_scalar(\$some_scalar); |
92
|
|
|
|
|
|
|
@ciphered = $cipher->encipher_list(@list); |
93
|
|
|
|
|
|
|
@list = $cipher->decipher_list(@ciphered); |
94
|
|
|
|
|
|
|
$cipher->encipher_array(\@some_array); |
95
|
|
|
|
|
|
|
$cipher->decipher_array(\@some_array); |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
#Other uses |
98
|
|
|
|
|
|
|
$null_cipher = new Text::Cipher::KeywordAlphabet(); #no-op cipher |
99
|
|
|
|
|
|
|
$rot13_cipher = new Text::Cipher::KeywordAlphabet(undef, 13); #Caesar cipher |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=head1 DESCRIPTION |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
This module generates a monoalphabetic substitution cipher from a set of words, resulting in what's sometimes referred to as a "keyword (generated) alphabet". |
104
|
|
|
|
|
|
|
Here's a good definition, plagiarised from an anonymous source: |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
"A keyword alphabet is formed by taking a word or phrase, deleting the second and subsequent occurrence of each letter and then writing the remaining letters of the alphabet in order. |
107
|
|
|
|
|
|
|
Encipherment is achieved by replacing each plaintext letter by the letter that appears N letters later in the (cyclic) keyword alphabet." |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
The keyword alphabet is case-insensitive - both uppercase and lowercase characters will be transformed with the same mapping. |
110
|
|
|
|
|
|
|
The offset (N in the definition above) can be a positive or negative integer. |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
L is an introductory tutorial on how substitution ciphers can be broken. |
113
|
|
|
|
|
|
|
L contains a full worked example. |
114
|
|
|
|
|
|
|
L provides an online substitution cipher breaker. |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
At the risk of stating the obvious, since substitution ciphers are easy to break, it's advisable not to use them for protecting important data. |
117
|
|
|
|
|
|
|
Look at some of the more heavy-duty ciphers in the Crypt:: namespace which plug into Crypt::CBC if you want to protect data. |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=head1 METHODS |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=over 4 |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=item $obj = new Text::Cipher::KeywordAlphabet($keyword_phrase, $offset) |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
Create a new keyword alphabet |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=item $keyword_alphabet = $obj->alphabet(); |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
Return the keyword alphabet created by the constructor |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=item $ciphered = $obj->encipher($message) |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
Enciphers a string using the keyword alphabet |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=item $message = $obj->decipher($ciphered) |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
Reverse of encipher() |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=item $obj->encipher_scalar(\$some_scalar); |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
By-reference equivalent of encipher() |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=item $obj->decipher_scalar(\$some_scalar); |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
By-reference equivalent of decipher() |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=item @ciphered = $obj->encipher_list(@list); |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
Convenience method provided by Text::Cipher |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=item @list = $obj->decipher_list(@ciphered); |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
Reverse of encipher_list(). |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=item $obj->encipher_array(\@some_array); |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Convenience method provided by Text::Cipher |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=item $obj->decipher_array(\@some_array); |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
Reverse of encipher_array(). |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=back |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=head1 VERSION |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
See $Text::Cipher::KeywordAlphabet::VERSION. |
168
|
|
|
|
|
|
|
Last edit: $Revision: 1.5 $ on $Date: 2005/03/20 20:02:11 $ |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=head1 BUGS |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
None known. This module has not been used heavily in production so it's not impossible a bug may have slipped through the unit tests. |
173
|
|
|
|
|
|
|
Bug reports are welcome, particularly with patches & test cases. |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=head1 AUTHOR |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
John Alden |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head1 SEE ALSO |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=over 4 |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=item Text::Cipher and Regexp::Tr |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
Useful building blocks for substitution ciphers |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=item Text::Shift and Crypt::Rot13 |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
Caesar (aka shift or rot-N) ciphers (see L) |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=item Crypt::Caesar |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
Crack Caesar ciphers using letter frequency (see L) |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=item Crypt::Vigenere |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Vigenere polyalphabetic cipher (see L) |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=item Crypt::Enigma and Crypt::OOEnigma |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
Implementations of Enigma ciphers (see L) |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=back |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
Copyright 2005 by John Alden |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=cut |