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