File Coverage

blib/lib/Net/DNS/SEC/RSA.pm
Criterion Covered Total %
statement 34 34 100.0
branch 8 8 100.0
condition n/a
subroutine 9 9 100.0
pod 2 2 100.0
total 53 53 100.0


line stmt bran cond sub pod time code
1             package Net::DNS::SEC::RSA;
2              
3 12     12   47916 use strict;
  12         47  
  12         385  
4 12     12   72 use warnings;
  12         23  
  12         652  
5              
6             our $VERSION = (qw$Id: RSA.pm 1863 2022-03-14 14:59:21Z willem $)[2];
7              
8              
9             =head1 NAME
10              
11             Net::DNS::SEC::RSA - DNSSEC RSA digital signature algorithm
12              
13              
14             =head1 SYNOPSIS
15              
16             require Net::DNS::SEC::RSA;
17              
18             $signature = Net::DNS::SEC::RSA->sign( $sigdata, $private );
19              
20             $validated = Net::DNS::SEC::RSA->verify( $sigdata, $keyrr, $sigbin );
21              
22              
23             =head1 DESCRIPTION
24              
25             Implementation of RSA digital signature
26             generation and verification procedures.
27              
28             =head2 sign
29              
30             $signature = Net::DNS::SEC::RSA->sign( $sigdata, $private );
31              
32             Generates the wire-format signature from the sigdata octet string
33             and the appropriate private key object.
34              
35             =head2 verify
36              
37             $validated = Net::DNS::SEC::RSA->verify( $sigdata, $keyrr, $sigbin );
38              
39             Verifies the signature over the sigdata octet string using the specified
40             public key resource record.
41              
42             =cut
43              
44 12     12   79 use integer;
  12         22  
  12         88  
45 12     12   304 use MIME::Base64;
  12         32  
  12         1345  
46              
47 12     12   92 use constant RSA_configured => Net::DNS::SEC::libcrypto->can('EVP_PKEY_new_RSA');
  12         36  
  12         1049  
48              
49 12     12   5284 BEGIN { die 'RSA disabled or application has no "use Net::DNS::SEC"' unless RSA_configured }
50              
51              
52             my %parameters = (
53             1 => scalar eval { Net::DNS::SEC::libcrypto::EVP_md5() },
54             5 => scalar eval { Net::DNS::SEC::libcrypto::EVP_sha1() },
55             7 => scalar eval { Net::DNS::SEC::libcrypto::EVP_sha1() },
56             8 => scalar eval { Net::DNS::SEC::libcrypto::EVP_sha256() },
57             10 => scalar eval { Net::DNS::SEC::libcrypto::EVP_sha512() },
58             );
59              
60 12     12   225 sub _index { return keys %parameters }
61              
62              
63             sub sign {
64 12     12 1 39749 my ( $class, $sigdata, $private ) = @_;
65              
66 12         43 my $evpmd = $parameters{$private->algorithm};
67 12 100       70 die 'private key not RSA' unless $evpmd;
68              
69             my ( $n, $e, $d, $p, $q ) =
70 11         4501 map { decode_base64( $private->$_ ) } qw(Modulus PublicExponent PrivateExponent Prime1 Prime2);
  55         8343  
71              
72 11         446 my $evpkey = Net::DNS::SEC::libcrypto::EVP_PKEY_new_RSA( $n, $e, $d, $p, $q );
73              
74 11         63953 return Net::DNS::SEC::libcrypto::EVP_sign( $sigdata, $evpkey, $evpmd );
75             }
76              
77              
78             sub verify {
79 34     34 1 15295 my ( $class, $sigdata, $keyrr, $sigbin ) = @_;
80              
81 34         96 my $evpmd = $parameters{$keyrr->algorithm};
82 34 100       302 die 'public key not RSA' unless $evpmd;
83              
84 33 100       83 return unless $sigbin;
85              
86 32         76 my $keybin = $keyrr->keybin; # public key
87 32         270 my ( $short, $long ) = unpack( 'Cn', $keybin ); # RFC3110, section 2
88 32 100       105 my $keyfmt = $short ? "x a$short a*" : "x3 a$long a*";
89 32         158 my ( $exponent, $modulus ) = unpack( $keyfmt, $keybin );
90              
91 32         248 my $evpkey = Net::DNS::SEC::libcrypto::EVP_PKEY_new_RSA( $modulus, $exponent, '', '', '' );
92              
93 32         3262 return Net::DNS::SEC::libcrypto::EVP_verify( $sigdata, $sigbin, $evpkey, $evpmd );
94             }
95              
96              
97             1;
98              
99             __END__