File Coverage

blib/lib/Crypt/ProtectedString.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Crypt::ProtectedString;
2              
3 1     1   61073 use 5.008001;
  1         4  
  1         28  
4 1     1   4 use strict;
  1         2  
  1         27  
5 1     1   4 use warnings;
  1         5  
  1         58  
6              
7             our $VERSION = '0.00_01';
8             $VERSION = eval $VERSION; # see L
9              
10             # Format:
11             # VERSION$TYPE$CIPHERTEXT$DISPLAYTEXT$reserved fields for future use
12             #
13             # Version = #!PROTECTEDKEYID, where PROTECTEDKEYID is an integer reference
14             # to the protected key to use...
15             #
16             # For credit cards: TYPE=cc-number, optional field 1 = plaintext exp. date
17             # For example: #!1$CC$base64-string-here$**** **** **** 1234$12/08$
18             #
19             # For passwords: TYPE=password, DISPLAYTEXT= empty ($$).
20              
21 0           use Module::Pluggable ( search_path => ['Crypt::ProtectedString::Types'],
22 1     1   493 instantiate => 'new' );
  0            
23             use Carp;
24              
25             our $delimiter = '$';
26             our $version_string = '#!1';
27              
28             sub _choose_best {
29             my $query = shift;
30             my $prio_method = shift;
31             my $exec_method = shift;
32              
33             my @priorities;
34              
35             foreach my $plugin ( plugins() ) {
36             if ($plugin->can($prio_method) && $plugin->can($exec_method)) {
37             my $priority = $plugin->$prio_method($query);
38             push @priorities, [$plugin, $priority];
39             }
40             }
41              
42             @priorities = sort {$b->[1] <=> $a->[1]} @priorities;
43             return $priorities[0]->[0];
44             }
45              
46             sub new {
47             my $class = shift;
48            
49             if ($#_ == -1) {
50             return __PACKAGE__->_new_blank($class);
51             } elsif ($#_ == 0) {
52             my $protectedstr = shift;
53              
54             return __PACKAGE__->_new_from_protected($class, $protectedstr);
55             } elsif ($#_ == 1) {
56             my $datatype = shift;
57             my $plaintext = shift;
58            
59             return __PACKAGE__->_new_from_plaintext($class, $datatype, $plaintext);
60             } else {
61             die("Invalid number of arguments in Secrets");
62             }
63              
64             }
65              
66             sub _new_blank {
67             my $class = shift;
68             my $self;
69             $self->{protected} = '';
70             bless $self, $class;
71             }
72              
73             sub _new_from_protected {
74             my $class = shift;
75             my $protectedstr = shift;
76             my $self;
77             $self->{protected} = $protectedstr;
78             return bless $self, $class;
79             }
80              
81             sub _new_from_plaintext {
82             my $class = shift;
83             my $type = shift;
84             my $plaintext = shift;
85             my $self;
86             bless $self, $class;
87            
88             $self->{protected} = $self->protect($type,$plaintext);
89              
90             return $self;
91             }
92              
93             sub display {
94             my $self = shift;
95             my @parr;
96             my $protectedstr = $self->{protected};
97             if ($#_ == -1) {
98             @parr = split(/$delimiter/, $self->{protected}, 5);
99             return $parr[3];
100             }
101             elsif($#_ == 0) {
102             $protectedstr = $_[0];
103             @parr = split(/$delimiter/, $protectedstr, 5);
104             return $parr[3];
105             }
106             elsif($#_ == 1) {
107             my $type = $_[0];
108             my $plaintext = $_[1];
109             my $displayer = __PACKAGE__->_choose_best($type,'can_display','display');
110             return $displayer->display($type, $plaintext);
111             }
112             else { die("Invalid arguments to ProtectedString create_display."); }
113             }
114              
115             sub _protect {
116             my $type = shift;
117             my $plaintext = shift;
118             my $displaytext = shift;
119             my $ciphertext = __PACKAGE__->_encrypt($type, $plaintext, $version_string);
120              
121             return join ($delimiter, $version_string, $type, $ciphertext, $displaytext, @_);
122             }
123              
124             sub protect {
125             my $self = shift;
126             my $type = shift;
127             my $plaintext = shift;
128             my $displaytext = $self->display($type, $plaintext);
129              
130             $self->{protected} = __PACKAGE__->_protect($type,$plaintext,$displaytext, @_);
131              
132             return $self->{protected};
133             }
134              
135             sub _encrypt {
136             my $type = shift;
137             my $plaintext = shift;
138             my $keyid = shift;
139             $keyid ||= $version_string;
140             my $cryptkeeper = __PACKAGE__->_choose_best($type,'can_encrypt','encrypt');
141              
142             return $cryptkeeper->encrypt($type,$plaintext,$keyid);
143             }
144              
145             sub _decrypt {
146             my $type = shift;
147             my $ciphertext = shift;
148             my $keyid = shift;
149              
150             my $cryptkeeper = __PACKAGE__->_choose_best($type,'can_decrypt','decrypt');
151              
152             return $cryptkeeper->decrypt($type, $ciphertext, $keyid);
153             }
154              
155             sub decrypt {
156             my $self = shift;
157             my ($type,$ciphertext,$keyid);
158             if ($#_ == -1) {
159             my @parr = split(/$delimiter/, $self->{protected}, 5);
160             $type = $parr[1];
161             $ciphertext = $parr[2];
162             $keyid = $parr[0];
163             } elsif($#_ == 0) {
164             my @parr = split(/$delimiter/, $_[0], 5);
165             $type = $parr[1];
166             $ciphertext = $parr[2];
167             $keyid = $parr[0];
168             } elsif($#_ == 1) {
169             $type = shift;
170             $ciphertext = shift;
171             $keyid = $version_string;
172             } elsif($#_ == 2) {
173             $type = shift;
174             $ciphertext = shift;
175             $keyid = shift;
176             $keyid ||= $version_string;
177             } else { die("Invalid arguments to ProtectedString decrypt."); }
178              
179             return __PACKAGE__->_decrypt($type,$ciphertext,$keyid);
180             }
181              
182             sub AS_STRING {
183             my $self = shift;
184              
185             return $self->{protected};
186              
187             }
188              
189             1;
190             __END__