File Coverage

lib/XML/Compile/WSS/Sign/RSA.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


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