File Coverage

blib/lib/Crypt/Nash.pm
Criterion Covered Total %
statement 51 51 100.0
branch 8 14 57.1
condition n/a
subroutine 7 7 100.0
pod 3 3 100.0
total 69 75 92.0


line stmt bran cond sub pod time code
1             package Crypt::Nash;
2 1     1   23829 use strict;
  1         2  
  1         109  
3              
4             our $DEBUG = 0;
5             our $VERSION = 0.1;
6              
7             =head1 NAME
8              
9             Crypt::Nash - Implementation of Nash Cryptosystem
10              
11             =head1 DESCRIPTION
12              
13             This is a self-synchronizing cipher feedback stream cipher
14             proposed by John Nash in 1950, just recently declassified.
15              
16             =head1 NOTES
17              
18             -- Nash doesn't say anything about the initial state of the bits
19             in the system; here we allow an initial state as part of the key
20             It would be reasonable and interesting to consider other
21             possibilities, such as having a fixed initial state (all zeros),
22             or running the system with "0"'s as input for a while to arrive
23             at an initial state, or ... ??
24              
25             -- We implement the example given in his note. There is one arrow
26             missing a label; we assume here the missing label is a "+".
27             We also choose an arbitrary starting state as part of the key.
28              
29             -- There are many interesting open questions about this system;
30             here are some as ``food for thought'':
31             (a) Are there ``weak keys''? (Keys that shouldn't be used?)
32             (b) If the system receives periodic input, it will exhibit
33             periodic output. (E.g. input 001001001001001...)
34             What can be said about the periodicities?
35             (c) How do different guesses about what Nash intended
36             for the starting state affect security?
37             (d) How long can a given bit circulate internally?
38             (e) Can you figure out the permutations and bit-flips if you are allowed
39             to specify inputs to the system, and to reset it to
40             the initial state whenever you like? (Effectively, a
41             chosen ciphertext attack)
42             (f) Is the output of the system balanced (equal number of 0's and 1's)
43             or unbalanced (biased somehow)?
44              
45             =head1 METHODS
46              
47             =cut
48              
49            
50             =head2 new , , , , ,
51              
52             =over 4
53              
54             =item n - number of state bits (not counting D, P entry point, or output bit)
55              
56             =item red permutation - specifies the red permutation: redp[i] says where bit i comes from, in the red permutation
57              
58             =item red bits - 1 = complement, 0 = no complement
59              
60             =item blue permutation - blue permutation
61              
62             =item blue bits - same as for redbits
63              
64             =item initial permuatation - initial state P[0...n] and P[n+1]=output bit. P[0] is entry point
65              
66             =back
67              
68             =cut
69             sub new {
70 2     2 1 22 my $class = shift;
71 2         3 my $n = shift;
72 2         3 my $red_p = shift;
73 2         3 my $red_bits = shift;
74 2         2 my $blue_p = shift;
75 2         3 my $blue_bits = shift;
76 2         3 my $initial_p = shift;
77              
78 1     1   1186 use Data::Dumper;
  1         13516  
  1         642  
79 2 50       6 die "Red p is not $n+2" unless $n+2 == scalar(@$red_p);
80 2 50       5 die "Red b is not $n+2" unless $n+2 == scalar(@$red_bits);
81 2 50       5 die "Blue p is not $n+2" unless $n+2 == scalar(@$blue_p);
82 2 50       6 die "Blue b is not $n+2" unless $n+2 == scalar(@$blue_bits);
83 2 50       6 die "Init p is not $n+2" unless $n+2 == scalar(@$initial_p);
84            
85 2         19 return bless {
86             n => $n,
87             red_p => $red_p,
88             red_bits => $red_bits,
89             blue_p => $blue_p,
90             blue_bits => $blue_bits,
91             p => $initial_p,
92             }, $class;
93             }
94              
95             # advance state for one tick, with input ciphertext bit c.
96             sub _tick {
97 28     28   31 my $self = shift;
98 28         29 my $c = shift;
99 28 100       44 if (0==$c) {
100             # use blue permutation
101             # copy P[bluep[[i]] to P[i], complementing if bluebits[i]==1 (a "-" label on the blue arrow)
102 6         14 $self->{p} = [ map { $self->{p}->[$self->{blue_p}->[$_]] ^ $self->{blue_bits}->[$_] } (0..$self->{n}+1) ];
  48         107  
103             } else {
104             # use red permutation
105             # copy P[redp[[i]] to P[i], complementing if redbits[i]==1 (a "-" label on the red arrow)
106 22         43 $self->{p} = [ map { $self->{p}->[$self->{red_p}->[$_]] ^ $self->{red_bits}->[$_] } (0..$self->{n}+1) ];
  176         338  
107             }
108             # entry point of P gets new bit
109 28         77 $self->{p}->[0] = $c;
110 28         40 _DEBUG("State: ".$c." ".join("", @{$self->{p}}));
  28         100  
111             }
112              
113             =head2 encrypt
114              
115             Encrypt bitstring, return ciphertext string
116              
117             =cut
118             sub encrypt {
119 1     1 1 2 my $self = shift;
120 1         2 my $bs = shift;
121 1         2 my $cs = [];
122 1         10 _DEBUG("Encrypt: encrypting string bs = ".join("", @$bs));
123 1         2 foreach my $b (@$bs) {
124 14         20 my $c = $b ^ $self->{p}->[-1];
125 14         16 push @$cs, $c;
126 14         23 $self->_tick($c);
127             }
128 1         7 _DEBUG("Encrypt: ciphertext string cs = ".join("", @$cs));
129 1         4 return $cs;
130             }
131              
132             =head2 decrypt
133              
134             Decrypt bitstring, return ciphertext string
135              
136             =cut
137             sub decrypt {
138 1     1 1 2 my $self = shift;
139 1         2 my $cs = shift;
140 1         2 my $bs = [];
141 1         7 _DEBUG("Decrypt: decrypting string cs = ".join("", @$cs));
142 1         2 foreach my $c (@$cs) {
143 14         24 my $b = $self->{p}->[-1] ^ $c;
144 14         26 $self->_tick($c);
145 14         72 push @$bs, $b;
146             }
147 1         8 _DEBUG("Decrypt: plaintext string bs = ".join("", @$bs));
148 1         4 return $bs;
149            
150             }
151              
152              
153             sub _DEBUG {
154 32     32   41 my $mess = shift;
155 32 50       91 warn $mess if $DEBUG;
156             }
157              
158             =head1 AUTHOR
159              
160             Python Implementation by Ronald L. Rivest (2/17/2012)
161              
162             Available here http://courses.csail.mit.edu/6.857/2012/files/nash.py
163              
164             Perl port by Simon Wistow
165              
166             =head1 LICENSE
167              
168             Distributed under the same terms as Perl itself
169              
170             =cut
171              
172             1;