|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # IP::Anonymous - Perl port of Crypto-PAn to provide anonymous IP addresses  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Copyright (c) 2005 John Kristoff .  All rights  | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # reserved.  This program is free software; you can redistribute it and/or  | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # modify it under the same terms as Perl itself.  | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package IP::Anonymous;  | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $VERSION = '0.04';  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 require 5.001;  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # base extensions and modules  | 
| 
12
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
8694
 | 
 use strict;                 # force us to code defensively  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
    | 
| 
13
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
6
 | 
 use warnings;               # do not let laziness go unnoticed  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
42
 | 
    | 
| 
14
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
 use vars qw($VERSION);      # package scope global vars  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
    | 
| 
15
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
 use Carp;                   # make errors the caller's problem  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
147
 | 
    | 
| 
16
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
1103
 | 
 use Socket;                 # for convenient dotted quad handling routines  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5898
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
614
 | 
    | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # additional modules  | 
| 
19
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
1433
 | 
 use Crypt::Rijndael;        # the Rijndael crypto magic  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2705
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
722
 | 
    | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # module scope vars  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $m_pad;                  # 2nd 128 bits of user key used for secret padding  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $ecb;                    # electronic codebook mode (default) object  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $first4bytes_pad;        # 1st 4 bytes of secret pad in "network" order  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # initialize  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
28
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
1
  
 | 
663
 | 
     my $package = shift;  | 
| 
29
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     my @key = @_;           # expected key is 32 8-bit unsigned ints  | 
| 
30
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     my $m_key;              # 1st 128 bits of user key used for cipher  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # 1st 128 bits of key used as secret key for Rijndael cipher  | 
| 
33
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     $m_key = pack("C16", @key[0..15]);  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # 2nd 128 bits of key used for secret padding  | 
| 
35
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     $m_pad = pack("C16", @key[16..31]);  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # init the key  | 
| 
38
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
     $ecb = new Crypt::Rijndael $m_key;  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # encrypt the 128-bit secret pad  | 
| 
40
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     $m_pad = $ecb->encrypt($m_pad);  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # first four bytes of secret pad in "network" (big-endian) order  | 
| 
43
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     $first4bytes_pad = unpack("N", $m_pad);  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
45
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     return bless({}, $package);  | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # generate a bit using the Rijndael cipher for each of the 32 bit address  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # msb bits taken from original address, remaining bits are from m_pad  | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub anonymize {  | 
| 
51
 | 
10
 | 
 
 | 
 
 | 
  
10
  
 | 
  
1
  
 | 
1337
 | 
     my $package = shift;  | 
| 
52
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     my $address = shift;    # expect dotted quad string  | 
| 
53
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
     my $first4bytes_input;  # used to handle the byte ordering problem  | 
| 
54
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
     my @rin_input = ();     # psuedorandom Rijndael cipher used each round  | 
| 
55
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
     my $rin_output;         # encrypted byte result at each round  | 
| 
56
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
     my $result = 0;         # initialize psuedorandom one time pad  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # rudimentary check for correctly formatted dotted quad  | 
| 
59
 | 
10
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
58
 | 
     if($address !~ /^\d{1,3}(?:\.\d{1,3}){3}$/) {  | 
| 
60
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         croak("ERROR [".__LINE__."]: invalid IP address format\n");  | 
| 
61
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return;  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # convert dotted quad to long in "network" (big-endian) order  | 
| 
65
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
53
 | 
     $address = unpack("N", pack("C4", split /\./, $address));  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Rijndael cipher used to obtain each of the 32 anonymized bits  | 
| 
68
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
45
 | 
     @rin_input = unpack("C16", $m_pad);  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # init input with encrypted pad   | 
| 
71
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     $rin_input[0] = ($first4bytes_pad >> 24);  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # mask off excess bits for 64-bit systems in left shift  | 
| 
73
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     $rin_input[1] = (($first4bytes_pad << 8 & 0xffffffff) >> 24);  | 
| 
74
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     $rin_input[2] = (($first4bytes_pad << 16 & 0xffffffff) >> 24);  | 
| 
75
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     $rin_input[3] = (($first4bytes_pad << 24 & 0xffffffff) >> 24);  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # get an 8-bit byte  | 
| 
78
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
     $rin_output = unpack("C", $ecb->encrypt(pack("C16", @rin_input)));  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # only the first bit of rin_output is used for each round  | 
| 
80
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
     $result |= ($rin_output >> 7) << 31;  | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # loop through remaining 31 bits  | 
| 
83
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
     for (my $position=1; $position <= 31; $position++) {  | 
| 
84
 | 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
459
 | 
         $first4bytes_input = (($address >> (32-$position)) <<  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                              (32-$position)) |  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                              # mask off excess bits for 64-bit systems  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                              (($first4bytes_pad << $position & 0xffffffff) >>  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                               $position);  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
90
 | 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
325
 | 
         $rin_input[0] = ($first4bytes_input >> 24);  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # mask off excess bits for 64-bit systems in left shift  | 
| 
92
 | 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
380
 | 
         $rin_input[1] = (($first4bytes_input << 8 & 0xffffffff) >> 24);  | 
| 
93
 | 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
372
 | 
         $rin_input[2] = (($first4bytes_input << 16 & 0xffffffff) >> 24);  | 
| 
94
 | 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
336
 | 
         $rin_input[3] = (($first4bytes_input << 24 & 0xffffffff) >> 24);  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # get an 8-bit byte  | 
| 
97
 | 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1183
 | 
         $rin_output = unpack("C", $ecb->encrypt(pack("C16", @rin_input)));  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # only the first bit of rin_output is used for each round  | 
| 
99
 | 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
909
 | 
         $result |= ($rin_output >> 7) << (31-$position);  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # return anonymized, prefix-preserved address as a dotted quad string  | 
| 
102
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
89
 | 
     return inet_ntoa(pack("N", $result ^ $address))  | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |