1package Net::DNS::SEC::ECDSA;
2
3use strict;
4use warnings;
5
6our $VERSION = (qw$Id: ECDSA.pm 1853 2021-10-11 10:40:59Z willem $)[2];
7
8
9=head1 NAME
10
11Net::DNS::SEC::ECDSA - DNSSEC ECDSA digital signature algorithm
12
13
14=head1 SYNOPSIS
15
16    require Net::DNS::SEC::ECDSA;
17
18    $signature = Net::DNS::SEC::ECDSA->sign( $sigdata, $private );
19
20    $validated = Net::DNS::SEC::ECDSA->verify( $sigdata, $keyrr, $sigbin );
21
22
23=head1 DESCRIPTION
24
25Implementation of ECDSA elliptic curve digital signature
26generation and verification procedures.
27
28=head2 sign
29
30    $signature = Net::DNS::SEC::ECDSA->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::ECDSA->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 ECDSA_configured => Net::DNS::SEC::libcrypto->can('EVP_PKEY_new_ECDSA');
48
49BEGIN { die 'ECDSA disabled or application has no "use Net::DNS::SEC"' unless ECDSA_configured }
50
51
52my %parameters = (
53	13 => [415, 32, Net::DNS::SEC::libcrypto::EVP_sha256()],
54	14 => [715, 48, Net::DNS::SEC::libcrypto::EVP_sha384()],
55	);
56
57sub _index { return keys %parameters }
58
59
60sub sign {
61	my ( $class, $sigdata, $private ) = @_;
62
63	my $algorithm = $private->algorithm;
64	my ( $nid, $keylen, $evpmd ) = @{$parameters{$algorithm} || []};
65	die 'private key not ECDSA' unless $nid;
66
67	my $rawkey = pack "a$keylen", decode_base64( $private->PrivateKey );
68	my $evpkey = Net::DNS::SEC::libcrypto::EVP_PKEY_new_ECDSA( $nid, $rawkey, '' );
69
70	my $asn1 = Net::DNS::SEC::libcrypto::EVP_sign( $sigdata, $evpkey, $evpmd );
71	return _ASN1decode( $asn1, $keylen );
72}
73
74
75sub verify {
76	my ( $class, $sigdata, $keyrr, $sigbin ) = @_;
77
78	my $algorithm = $keyrr->algorithm;
79	my ( $nid, $keylen, $evpmd ) = @{$parameters{$algorithm} || []};
80	die 'public key not ECDSA' unless $nid;
81
82	return unless $sigbin;
83
84	my ( $x, $y ) = unpack "a$keylen a$keylen", $keyrr->keybin;
85	my $evpkey = Net::DNS::SEC::libcrypto::EVP_PKEY_new_ECDSA( $nid, $x, $y );
86
87	my $asn1 = _ASN1encode( $sigbin, $keylen );
88	return Net::DNS::SEC::libcrypto::EVP_verify( $sigdata, $asn1, $evpkey, $evpmd );
89}
90
91
92########################################
93
94sub _ASN1encode {
95	my ( $sig, $size ) = @_;
96	my @part = unpack "a$size a$size", $sig;
97	my $length;
98	foreach (@part) {
99		s/^[\000]+//;
100		s/^$/\000/;
101		s/^(?=[\200-\377])/\000/;
102		$_ = pack 'C2 a*', 2, length, $_;
103		$length += length;
104	}
105	return pack 'C2 a* a*', 0x30, $length, @part;
106}
107
108sub _ASN1decode {
109	my ( $asn1, $size ) = @_;
110	my $n	 = unpack 'x3 C',	   $asn1;
111	my $m	 = unpack "x5 x$n C",	   $asn1;
112	my @part = unpack "x4 a$n x2 a$m", $asn1;
113	return pack 'a* a*', map { substr( pack( "x$size a*", $_ ), -$size ) } @part;
114}
115
116
1171;
118
119__END__
120
121########################################
122
123=head1 ACKNOWLEDGMENT
124
125Thanks are due to Eric Young and the many developers and
126contributors to the OpenSSL cryptographic library.
127
128
129=head1 COPYRIGHT
130
131Copyright (c)2014,2018 Dick Franks.
132
133All rights reserved.
134
135
136=head1 LICENSE
137
138Permission to use, copy, modify, and distribute this software and its
139documentation for any purpose and without fee is hereby granted, provided
140that the original copyright notices appear in all copies and that both
141copyright notice and this permission notice appear in supporting
142documentation, and that the name of the author not be used in advertising
143or publicity pertaining to distribution of the software without specific
144prior written permission.
145
146THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
147IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
148FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
149THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
150LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
151FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
152DEALINGS IN THE SOFTWARE.
153
154
155=head1 SEE ALSO
156
157L<Net::DNS>, L<Net::DNS::SEC>,
158RFC6090, RFC6605,
159L<OpenSSL|http://www.openssl.org/docs>
160
161=cut
162
163