1package Net::DNS::SEC::RSA;
2
3use strict;
4use warnings;
5
6our $VERSION = (qw$Id: RSA.pm 1853 2021-10-11 10:40:59Z willem $)[2];
7
8
9=head1 NAME
10
11Net::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
25Implementation of RSA digital signature
26generation and verification procedures.
27
28=head2 sign
29
30    $signature = Net::DNS::SEC::RSA->sign( $sigdata, $private );
31
32Generates the wire-format signature from the sigdata octet string
33and the appropriate private key object.
34
35=head2 verify
36
37    $validated = Net::DNS::SEC::RSA->verify( $sigdata, $keyrr, $sigbin );
38
39Verifies the signature over the sigdata octet string using the specified
40public key resource record.
41
42=cut
43
44use integer;
45use MIME::Base64;
46
47use constant RSA_configured => Net::DNS::SEC::libcrypto->can('EVP_PKEY_new_RSA');
48
49BEGIN { die 'RSA disabled or application has no "use Net::DNS::SEC"' unless RSA_configured }
50
51
52my %parameters = (
53	1  => Net::DNS::SEC::libcrypto::EVP_md5(),
54	5  => Net::DNS::SEC::libcrypto::EVP_sha1(),
55	7  => Net::DNS::SEC::libcrypto::EVP_sha1(),
56	8  => Net::DNS::SEC::libcrypto::EVP_sha256(),
57	10 => Net::DNS::SEC::libcrypto::EVP_sha512(),
58	);
59
60sub _index { return keys %parameters }
61
62
63sub sign {
64	my ( $class, $sigdata, $private ) = @_;
65
66	my $index = $private->algorithm;
67	my $evpmd = $parameters{$index} || die 'private key not RSA';
68
69	my ( $n, $e, $d, $p, $q ) =
70			map { decode_base64( $private->$_ ) } qw(Modulus PublicExponent PrivateExponent Prime1 Prime2);
71
72	my $evpkey = Net::DNS::SEC::libcrypto::EVP_PKEY_new_RSA( $n, $e, $d, $p, $q );
73
74	return Net::DNS::SEC::libcrypto::EVP_sign( $sigdata, $evpkey, $evpmd );
75}
76
77
78sub verify {
79	my ( $class, $sigdata, $keyrr, $sigbin ) = @_;
80
81	my $index = $keyrr->algorithm;
82	my $evpmd = $parameters{$index} || die 'public key not RSA';
83
84	return unless $sigbin;
85
86	my $keybin = $keyrr->keybin;				# public key
87	my ( $short, $long ) = unpack( 'Cn', $keybin );		# RFC3110, section 2
88	my $keyfmt = $short ? "x a$short a*" : "x3 a$long a*";
89	my ( $exponent, $modulus ) = unpack( $keyfmt, $keybin );
90
91	my $evpkey = Net::DNS::SEC::libcrypto::EVP_PKEY_new_RSA( $modulus, $exponent, '', '', '' );
92
93	return Net::DNS::SEC::libcrypto::EVP_verify( $sigdata, $sigbin, $evpkey, $evpmd );
94}
95
96
971;
98
99__END__
100
101########################################
102
103=head1 ACKNOWLEDGMENT
104
105Thanks are due to Eric Young and the many developers and
106contributors to the OpenSSL cryptographic library.
107
108
109=head1 COPYRIGHT
110
111Copyright (c)2014,2018 Dick Franks.
112
113All rights reserved.
114
115
116=head1 LICENSE
117
118Permission to use, copy, modify, and distribute this software and its
119documentation for any purpose and without fee is hereby granted, provided
120that the original copyright notices appear in all copies and that both
121copyright notice and this permission notice appear in supporting
122documentation, and that the name of the author not be used in advertising
123or publicity pertaining to distribution of the software without specific
124prior written permission.
125
126THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
127IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
128FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
129THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
130LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
131FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
132DEALINGS IN THE SOFTWARE.
133
134
135=head1 SEE ALSO
136
137L<Net::DNS>, L<Net::DNS::SEC>,
138RFC8017, RFC3110,
139L<OpenSSL|http://www.openssl.org/docs>
140
141=cut
142
143