File Coverage

lib/XML/Compile/WSS/Sign/RSA.pm
Criterion Covered Total %
statement 24 96 25.0
branch 0 50 0.0
condition 0 11 0.0
subroutine 8 25 32.0
pod 10 14 71.4
total 42 196 21.4


line stmt bran cond sub pod time code
1             # Copyrights 2012-2016 by [Mark Overmeer].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.02.
5 1     1   1109 use warnings;
  1         2  
  1         25  
6 1     1   3 use strict;
  1         1  
  1         23  
7              
8             package XML::Compile::WSS::Sign::RSA;
9 1     1   2 use vars '$VERSION';
  1         2  
  1         35  
10             $VERSION = '2.02';
11              
12 1     1   3 use base 'XML::Compile::WSS::Sign';
  1         1  
  1         53  
13              
14 1     1   3 use Log::Report 'xml-compile-wss-sig';
  1         2  
  1         3  
15              
16 1     1   164 use Crypt::OpenSSL::RSA ();
  1         1  
  1         14  
17 1     1   455 use File::Slurp qw/read_file/;
  1         2834  
  1         50  
18 1     1   4 use Scalar::Util qw/blessed/;
  1         1  
  1         777  
19              
20              
21             sub init($)
22 0     0 0   { my ($self, $args) = @_;
23 0           $self->SUPER::init($args);
24              
25             $self->privateKey
26             ( $args->{private_key}
27             , hashing => $args->{hashing}
28             , padding => $args->{padding}
29 0           );
30            
31             $self->publicKey
32             ( $args->{public_key}
33             , hashing => $args->{hashing}
34             , padding => $args->{padding}
35 0           );
36 0           $self;
37             }
38              
39             #-----------------
40              
41              
42             sub _setRSAflags($$%)
43 0     0     { my ($self, $key, $rsa, %args) = @_;
44 0 0         if(my $hashing = $args{hashing})
45 0           { my $use_hash = "use_\L$hashing\E_hash";
46 0 0         $rsa->can($use_hash)
47             or error __x"hash {type} not supported by {pkg}"
48             , type => $hashing, pkg => ref $key;
49 0           $rsa->$use_hash();
50             }
51              
52 0 0         if(my $padding = $args{padding})
53 0           { my $use_pad = "use_\L$padding\E_padding";
54 0 0         $rsa->can($use_pad)
55             or error __x"padding {type} not supported by {pkg}"
56             , type => $padding, pkg => ref $key;
57 0           $rsa->$use_pad();
58             }
59 0           $rsa;
60             }
61              
62             sub privateKey(;$%)
63 0     0 1   { my ($self, $priv) = (shift, shift);
64 0 0         defined $priv or return $self->{XCWSR_privkey};
65              
66 0           my ($key, $rsa) = $self->toPrivateSHA($priv);
67 0           $self->{XCWSR_privrsa} = $self->_setRSAflags($key, $rsa, @_);
68 0           $self->{XCWSR_privkey} = $key;
69 0           $key;
70             }
71              
72              
73             sub toPrivateSHA($)
74 0     0 1   { my ($self, $priv) = @_;
75              
76 0 0 0       return ($priv->get_private_key_string, $priv)
77             if blessed $priv && $priv->isa('Crypt::OpenSSL::RSA');
78              
79 0 0         error __x"unsupported private key object `{object}'", object=>$priv
80             if ref $priv =~ m/Crypt/;
81              
82 0 0         return ($priv, Crypt::OpenSSL::RSA->new_private_key($priv))
83             if index($priv, "\n") >= 0;
84              
85 0           my $key = read_file $priv;
86 0           my $rsa = eval { Crypt::OpenSSL::RSA->new_private_key($key) };
  0            
87 0 0         if($@)
88 0           { error __x"cannot read private RSA key from {file}: {err}"
89             , file => $priv, err => $@;
90             }
91              
92 0           ($key, $rsa);
93             }
94              
95              
96 0     0 1   sub privateKeyRSA() {shift->{XCWSR_privrsa}}
97              
98              
99             sub publicKey(;$%)
100 0     0 1   { my $self = shift;
101 0 0         my $pub = @_%2==1 ? shift : undef;
102              
103             return $self->{XCWSR_pubkey}
104 0 0 0       if !defined $pub && $self->{XCWSR_pubkey};
105              
106 0 0 0       my $token = $pub || $self->privateKeyRSA
107             or return;
108              
109 0           my ($key, $rsa) = $self->toPublicRSA($token);
110 0           $self->{XCWSR_pubrsa} = $self->_setRSAflags($key, $rsa, @_);
111 0           $self->{XCWSR_pubkey} = $pub;
112 0           $pub;
113             }
114              
115              
116             sub toPublicRSA($)
117 0     0 1   { my ($thing, $token) = @_;
118 0 0         defined $token or return;
119              
120 0 0         blessed $token
121             or panic "expects a public_key as object, not ".$token;
122              
123 0 0         return ($token->get_public_key_string, $token)
124             if $token->isa('Crypt::OpenSSL::RSA');
125              
126 0 0         $token = $token->certificate
127             if $token->isa('XML::Compile::WSS::SecToken::X509v3');
128              
129 0           my $key = $token->pubkey;
130 0 0         return ($key, Crypt::OpenSSL::RSA->new_public_key($key))
131             if $token->isa('Crypt::OpenSSL::X509');
132              
133 0           error __x"unsupported public key `{token}' for check RSA"
134             , token => $token;
135             }
136              
137              
138             sub publicKeyString($)
139 0     0 1   { my $rsa = shift->publicKeyRSA;
140 0   0       my $how = shift || '(NONE)';
141              
142 0 0         $how eq 'PKCS1' ? $rsa->get_public_key_string
    0          
143             : $how eq 'X509' ? $rsa->get_public_key_x509_string
144             : error __x"unknown public key string format `{name}'", name => $how;
145             }
146              
147              
148              
149 0     0 1   sub publicKeyRSA() {shift->{XCWSR_pubrsa}}
150            
151             #-----------------
152              
153             # Do we need next 4? Probably not
154              
155             sub sign(@)
156 0     0 0   { my ($self, $text) = @_;
157 0 0         my $priv = $self->privateKeyRSA
158             or error "signing rsa requires the private_key";
159              
160 0           $priv->sign($text);
161             }
162              
163             sub encrypt(@)
164 0     0 0   { my ($self, $text) = @_;
165 0 0         my $pub = $self->publicKeyRSA
166             or error "encrypting rsa requires the public_key";
167 0           $pub->encrypt($text);
168             }
169              
170             sub decrypt(@)
171 0     0 0   { my ($self, $text) = @_;
172 0 0         my $priv = $self->privateKeyRSA
173             or error "decrypting rsa requires the private_key";
174 0           $priv->decrypt($text);
175             }
176              
177              
178             sub check($$)
179 0     0 1   { my ($self, $text, $signature) = @_;
180 0 0         my $rsa = $self->publicKeyRSA
181             or error "checking signature with rsa requires the public_key";
182              
183 0           $rsa->verify($text, $signature);
184             }
185              
186             ### above functions probably not needed.
187              
188             sub builder()
189 0     0 1   { my ($self) = @_;
190 0 0         my $priv = $self->privateKeyRSA
191             or error "signing rsa requires the private_key";
192              
193 0     0     sub { $priv->sign($_[0]) };
  0            
194             }
195              
196             sub checker()
197 0     0 1   { my ($self) = @_;
198 0 0         my $pub = $self->publicKeyRSA
199             or error "checking signature with rsa requires the public_key";
200              
201             sub { # ($text, $signature)
202 0     0     $pub->verify($_[0], $_[1]);
203 0           };
204             }
205              
206             #-----------------
207              
208             1;