File Coverage

blib/lib/Crypt/PK/DSA.pm
Criterion Covered Total %
statement 95 100 95.0
branch 57 84 67.8
condition 14 37 37.8
subroutine 16 17 94.1
pod 4 10 40.0
total 186 248 75.0


line stmt bran cond sub pod time code
1             package Crypt::PK::DSA;
2              
3 6     6   167942 use strict;
  6         8  
  6         169  
4 6     6   28 use warnings;
  6         6  
  6         689  
5             our $VERSION = '0.089_002';
6              
7             require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
8             our %EXPORT_TAGS = ( all => [qw( dsa_encrypt dsa_decrypt dsa_sign_message dsa_verify_message dsa_sign_hash dsa_verify_hash )] );
9             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
10             our @EXPORT = qw();
11              
12 6     6   27 use Carp;
  6         8  
  6         388  
13             $Carp::Internal{(__PACKAGE__)}++;
14 6     6   807 use CryptX;
  6         15  
  6         206  
15 6     6   805 use Crypt::Misc qw(read_rawfile encode_b64 decode_b64 pem_to_der der_to_pem);
  6         10  
  6         349  
16 6     6   1398 use Crypt::PK;
  6         13  
  6         7346  
17              
18             sub new {
19 82     82 1 513203 my $self = shift->_new();
20 82 100       1174 return @_ > 0 ? $self->import_key(@_) : $self;
21             }
22              
23             sub generate_key {
24 8     8 1 1441 my $self = shift;
25 8 100       2737966 return $self->_generate_key_size(@_) if @_ == 2;
26 3 100 66     22 if (@_ == 1 && ref $_[0] eq 'HASH') {
    50 33        
27 1         2 my $param = shift;
28 1 50       4 my $p = $param->{p} or croak "FATAL: 'p' param not specified";
29 1 50       3 my $q = $param->{q} or croak "FATAL: 'q' param not specified";
30 1 50       3 my $g = $param->{g} or croak "FATAL: 'g' param not specified";
31 1         3 $p =~ s/^0x//;
32 1         1 $q =~ s/^0x//;
33 1         3 $g =~ s/^0x//;
34 1 50       2 croak "FATAL: 'p' param is empty after stripping '0x' prefix" unless length $p;
35 1 50       2 croak "FATAL: 'q' param is empty after stripping '0x' prefix" unless length $q;
36 1 50       3 croak "FATAL: 'g' param is empty after stripping '0x' prefix" unless length $g;
37 1         815 return $self->_generate_key_pqg_hex($p, $q, $g);
38             }
39             elsif (@_ == 1 && ref $_[0] eq 'SCALAR') {
40 2         3 my $data = ${$_[0]};
  2         4  
41 2 100       17 if ($data =~ /-----BEGIN DSA PARAMETERS-----\s*(.+)\s*-----END DSA PARAMETERS-----/s) {
42 1 50       6 $data = pem_to_der($data) or croak "FATAL: PEM/params decode failed";
43             }
44 2         7132 return $self->_generate_key_dsaparam($data);
45             }
46 0         0 croak "FATAL: DSA generate_key - invalid args";
47             }
48              
49             sub export_key_pem {
50 11     11 1 3029 my ($self, $type, $password, $cipher) = @_;
51             # public_x509 uses the same DER as public, just different PEM header
52 11 100 50     48 my $der_type = ($type || '') eq 'public_x509' ? 'public' : ($type || '');
      50        
53 11         520 my $key = $self->export_key_der($der_type);
54 11 50       22 return unless $key;
55 11 100       33 return der_to_pem($key, "DSA PRIVATE KEY", $password, $cipher) if $type eq 'private';
56 6 100       23 return der_to_pem($key, "DSA PUBLIC KEY") if $type eq 'public';
57 1 50       12 return der_to_pem($key, "PUBLIC KEY") if $type eq 'public_x509';
58             }
59              
60             sub import_key {
61 83     83 1 28205 my ($self, $key, $password) = @_;
62 83 50       241 croak "FATAL: undefined key" unless $key;
63              
64             # special case
65 83 100       216 if (ref($key) eq 'HASH') {
66 2 50 33     22 if ($key->{p} && $key->{q} && $key->{g} && $key->{y}) {
      33        
      33        
67             # hash exported via key2hash
68 2         8557 return $self->_import_hex($key->{p}, $key->{q}, $key->{g}, $key->{x}, $key->{y});
69             }
70             }
71              
72 81         113 my $data;
73 81 100       1333 if (ref($key) eq 'SCALAR') {
    50          
74 36         57 $data = $$key;
75             }
76             elsif (-f $key) {
77 45         191 $data = read_rawfile($key);
78             }
79             else {
80 0         0 croak "FATAL: non-existing file '$key'";
81             }
82 81 50       232 croak "FATAL: invalid key data" unless $data;
83              
84 81 100       659 if ($data =~ /-----BEGIN (DSA PRIVATE|DSA PUBLIC|PRIVATE|ENCRYPTED PRIVATE|PUBLIC) KEY-----(.+?)-----END (DSA PRIVATE|DSA PUBLIC|PRIVATE|ENCRYPTED PRIVATE|PUBLIC) KEY-----/s) {
    50          
    100          
    100          
    100          
85 20         38554 return $self->_import_pem($data, $password);
86             }
87             elsif ($data =~ /-----BEGIN CERTIFICATE-----(.+?)-----END CERTIFICATE-----/s) {
88 0         0 return $self->_import_pem($data, undef);
89             }
90             elsif ($data =~ /-----BEGIN OPENSSH PRIVATE KEY-----(.+?)-----END OPENSSH PRIVATE KEY-----/s) {
91 2         211710 return $self->_import_openssh($data, $password);
92             }
93             elsif ($data =~ /---- BEGIN SSH2 PUBLIC KEY ----(.+?)---- END SSH2 PUBLIC KEY ----/s) {
94 1         403 return $self->_import_openssh($data, undef);
95             }
96             elsif ($data =~ /ssh-dss\s+(\S+)/) {
97 1         11 $data = decode_b64("$1");
98 1         8 my ($typ, $p, $q, $g, $y) = Crypt::PK::_ssh_parse($data);
99 1 50 33     820 return $self->_import_hex(unpack('H*',$p), unpack('H*',$q), unpack('H*',$g), undef, unpack('H*',$y)) if $typ && $p && $q && $g && $y && $typ eq 'ssh-dss';
      33        
      33        
      33        
      33        
100             }
101             else {
102 57   33     86 my $rv = eval { $self->_import($data) } || eval { $self->_import_pkcs8($data, $password) };
103 57 50       467 return $rv if $rv;
104             }
105 0         0 croak "FATAL: invalid or unsupported DSA key format";
106             }
107              
108             ### FUNCTIONS
109              
110             sub dsa_encrypt { # legacy/obsolete
111 2     2 0 675 my $key = shift;
112 2         11 local $SIG{__DIE__} = \&CryptX::_croak;
113 2 100       11 $key = __PACKAGE__->new($key) unless ref $key;
114 2 100       213 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
115 1         3311 return $key->encrypt(@_);
116             }
117              
118             sub dsa_decrypt { # legacy/obsolete
119 1     1 0 282 my $key = shift;
120 1         4 local $SIG{__DIE__} = \&CryptX::_croak;
121 1 50       9 $key = __PACKAGE__->new($key) unless ref $key;
122 1 50       5 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
123 1         1681 return $key->decrypt(@_);
124             }
125              
126             sub dsa_sign_message { # legacy/obsolete
127 1     1 0 267 my $key = shift;
128 1         4 local $SIG{__DIE__} = \&CryptX::_croak;
129 1 50       8 $key = __PACKAGE__->new($key) unless ref $key;
130 1 50       5 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
131 1         1723 return $key->sign_message(@_);
132             }
133              
134             sub dsa_verify_message { # legacy/obsolete
135 1     1 0 276 my $key = shift;
136 1         4 local $SIG{__DIE__} = \&CryptX::_croak;
137 1 50       7 $key = __PACKAGE__->new($key) unless ref $key;
138 1 50       4 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
139 1         3292 return $key->verify_message(@_);
140             }
141              
142             sub dsa_sign_hash { # legacy/obsolete
143 1     1 0 283 my $key = shift;
144 1         5 local $SIG{__DIE__} = \&CryptX::_croak;
145 1 50       8 $key = __PACKAGE__->new($key) unless ref $key;
146 1 50       5 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
147 1         1723 return $key->sign_hash(@_);
148             }
149              
150             sub dsa_verify_hash { # legacy/obsolete
151 1     1 0 286 my $key = shift;
152 1         5 local $SIG{__DIE__} = \&CryptX::_croak;
153 1 50       7 $key = __PACKAGE__->new($key) unless ref $key;
154 1 50       5 croak "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
155 1         3266 return $key->verify_hash(@_);
156             }
157              
158 0     0     sub CLONE_SKIP { 1 } # prevent cloning
159              
160             1;
161              
162             =pod
163              
164             =head1 NAME
165              
166             Crypt::PK::DSA - Public key cryptography based on DSA
167              
168             =head1 SYNOPSIS
169              
170             ### OO interface
171              
172             my $message = 'hello world';
173             my $signer = Crypt::PK::DSA->new();
174             $signer->generate_key(30, 256);
175              
176             my $signature = $signer->sign_message($message, 'SHA256');
177             my $public_der = $signer->export_key_der('public');
178             my $verifier = Crypt::PK::DSA->new(\$public_der);
179             $verifier->verify_message($signature, $message, 'SHA256') or die "ERROR";
180              
181             my $ciphertext = $verifier->encrypt("secret message");
182             my $plaintext = $signer->decrypt($ciphertext);
183              
184             my $private_der = $signer->export_key_der('private');
185             my $private_pem = $signer->export_key_pem('private');
186             my $public_pem = $verifier->export_key_pem('public');
187              
188             =head1 DESCRIPTION
189              
190             DSA is primarily a digital signature scheme. In this module, signing and
191             verification are the most common operations and therefore the primary examples.
192              
193             Legacy function-style wrappers still exist in code for backwards compatibility,
194             but they are intentionally undocumented.
195              
196             =head1 METHODS
197              
198             =head2 new
199              
200             my $source = Crypt::PK::DSA->new();
201             $source->generate_key(20, 128);
202              
203             my $public_der = $source->export_key_der('public');
204             my $pub = Crypt::PK::DSA->new(\$public_der);
205              
206             my $private_pem = $source->export_key_pem('private', 'secret', 'AES-256-CBC');
207             my $priv = Crypt::PK::DSA->new(\$private_pem, 'secret');
208              
209             Passing C<$filename> or C<\$buffer> to C is equivalent: both forms
210             immediately import the key material into the new object.
211              
212             =head2 generate_key
213              
214             Uses the bundled C PRNG via libtomcrypt's C.
215             Returns the object itself (for chaining).
216              
217             $pk->generate_key($group_size, $modulus_size);
218             # $group_size ... [integer] size of the subgroup (q) in bytes; must satisfy: 15 < $group_size < 1024
219             # $modulus_size .. [integer] size of the prime (p) in bytes; must satisfy: ($modulus_size - $group_size) < 512
220             # $modulus_size must be >= $group_size
221             #
222             # The two-integer form uses Perl's usual numeric-to-integer coercion before
223             # the XS call. Callers should therefore pass exact integers; values like
224             # C<10.9> or C<"1e1"> will be coerced according to Perl's integer conversion.
225              
226             ### Common parameter pairs (group_size, modulus_size) => security level:
227             # generate_key(20, 128) => 80-bit security (1024-bit p, 160-bit q)
228             # generate_key(30, 256) => 120-bit security (2048-bit p, 240-bit q)
229             # generate_key(32, 256) => 128-bit security (2048-bit p, 256-bit q)
230             # generate_key(35, 384) => ~140-bit security (3072-bit p, 280-bit q)
231             # 140 bits => generate_key(35, 384)
232             # 160 bits => generate_key(40, 512)
233              
234             ### Sizes according section 4.2 of FIPS 186-4
235             # (L and N are the bit lengths of p and q respectively)
236             # L = 1024, N = 160 => generate_key(20, 128)
237             # L = 2048, N = 224 => generate_key(28, 256)
238             # L = 2048, N = 256 => generate_key(32, 256)
239             # L = 3072, N = 256 => generate_key(32, 384)
240              
241             $pk->generate_key($param_hash)
242             # $param_hash is { p => $p, q => $q, g => $g }
243             # where $p, $q, $g are hex strings
244              
245             $pk->generate_key(\$dsa_param)
246             # $dsa_param is the content of DER or PEM file with DSA params
247             # e.g. openssl dsaparam 2048
248              
249             =head2 import_key
250              
251             Loads private or public key in DER or PEM format.
252              
253             my $source = Crypt::PK::DSA->new();
254             $source->generate_key(20, 128);
255              
256             my $public_der = $source->export_key_der('public');
257             my $pub = Crypt::PK::DSA->new();
258             $pub->import_key(\$public_der);
259              
260             my $private_pem = $source->export_key_pem('private', 'secret', 'AES-256-CBC');
261             my $priv = Crypt::PK::DSA->new();
262             $priv->import_key(\$private_pem, 'secret');
263              
264             The same method also accepts filenames instead of buffers.
265              
266             Loading private or public keys from a Perl HASH:
267              
268             $pk->import_key($hashref);
269              
270             # where $hashref is a key exported via key2hash
271             $pk->import_key({
272             p => "AAF839A764E04D80824B79FA1F0496C093...", #prime modulus
273             q => "D05C4CB45F29D353442F1FEC43A6BE2BE8...", #prime divisor
274             g => "847E8896D12C9BF18FE283AE7AD58ED7F3...", #generator of a subgroup of order q in GF(p)
275             x => "6C801901AC74E2DC714D75A9F6969483CF...", #private key, random 0 < x < q
276             y => "8F7604D77FA62C7539562458A63C7611B7...", #public key, where y = g^x mod p
277             });
278              
279             Supported key formats:
280              
281             =over
282              
283             =item * DSA public keys
284              
285             -----BEGIN PUBLIC KEY-----
286             MIIBtjCCASsGByqGSM44BAEwggEeAoGBAJKyu+puNMGLpGIhbD1IatnwlI79ePr4
287             YHe2KBhRkheKxWUZRpN1Vd/+usS2IHSJ9op5cSWETiP05d7PMtJaitklw7jhudq3
288             GxNvV/GRdCQm3H6d76FHP88dms4vcDYc6ry6wKERGfNEtZ+4BAKrMZK+gDYsF4Aw
289             U6WVR969kYZhAhUA6w25FgSRmJ8W4XkvC60n8Wv3DpMCgYA4ZFE+3tLOM24PZj9Z
290             rxuqUzZZdR+kIzrsIYpWN9ustbmdKLKwsqIaUIxc5zxHEhbAjAIf8toPD+VEQIpY
291             7vgJgDhXuPq45BgN19iLTzOJwIhAFXPZvnAdIo9D/AnMw688gT6g6U8QCZwX2XYg
292             ICiVcriYVNcjVKHSFY/X0Oi7CgOBhAACgYB4ZTn4OYT/pjUd6tNhGPtOS3CE1oaj
293             5ScbetXg4ZDpceEyQi8VG+/ZTbs8var8X77JdEdeQA686cAxpOaVgW8V4odvcmfA
294             BfueiGnPXjqGfppiHAyL1Ngyd+EsXKmKVXZYAVFVI0WuJKiZBSVURU7+ByxOfpGa
295             fZhibr0SggWixQ==
296             -----END PUBLIC KEY-----
297              
298             =item * DSA private keys
299              
300             -----BEGIN DSA PRIVATE KEY-----
301             MIIBuwIBAAKBgQCSsrvqbjTBi6RiIWw9SGrZ8JSO/Xj6+GB3tigYUZIXisVlGUaT
302             dVXf/rrEtiB0ifaKeXElhE4j9OXezzLSWorZJcO44bnatxsTb1fxkXQkJtx+ne+h
303             Rz/PHZrOL3A2HOq8usChERnzRLWfuAQCqzGSvoA2LBeAMFOllUfevZGGYQIVAOsN
304             uRYEkZifFuF5LwutJ/Fr9w6TAoGAOGRRPt7SzjNuD2Y/Wa8bqlM2WXUfpCM67CGK
305             VjfbrLW5nSiysLKiGlCMXOc8RxIWwIwCH/LaDw/lRECKWO74CYA4V7j6uOQYDdfY
306             i08zicCIQBVz2b5wHSKPQ/wJzMOvPIE+oOlPEAmcF9l2ICAolXK4mFTXI1Sh0hWP
307             19DouwoCgYB4ZTn4OYT/pjUd6tNhGPtOS3CE1oaj5ScbetXg4ZDpceEyQi8VG+/Z
308             Tbs8var8X77JdEdeQA686cAxpOaVgW8V4odvcmfABfueiGnPXjqGfppiHAyL1Ngy
309             d+EsXKmKVXZYAVFVI0WuJKiZBSVURU7+ByxOfpGafZhibr0SggWixQIVAL7Sia03
310             8bvANjjL9Sitk8slrM6P
311             -----END DSA PRIVATE KEY-----
312              
313             =item * DSA private keys in password protected PEM format:
314              
315             -----BEGIN DSA PRIVATE KEY-----
316             Proc-Type: 4,ENCRYPTED
317             DEK-Info: DES-CBC,227ADC3AA0299491
318              
319             UISxBYAxPQMl2eK9LMAeHsssF6IxO+4G2ta2Jn8VE+boJrrH3iSTKeMXGjGaXl0z
320             DwcLGV+KMR70y+cxtTb34rFy+uSpBy10dOQJhxALDbe1XfCDQIUfaXRfMNA3um2I
321             JdZixUD/zcxBOUzao+MCr0V9XlJDgqBhJ5EEr53XHH07Eo5fhiBfbbR9NzdUPFrQ
322             p2ASyZtFh7RXoIBUCQgg21oeLddcNWV7gd/Y46kghO9s0JbJ8C+IsuWEPRSq502h
323             tSoDN6B0sxbVvOUICLLbQaxt7yduTAhRxVIJZ1PWATTVD7CZBVz9uIDZ7LOv+er2
324             1q3vkwb8E9spPsA240+BnfD571XEop4jrawxC0VKQZ+3cPVLc6jhIsxvzzFQUt67
325             g66v8GUgt7KF3KhVV7qEtntybQWDWb+K/uTIH9Ra8nP820d3Rnl61pPXDPlluteT
326             WSLOvEMN2zRmkaxQNv/tLdT0SYpQtdjw74G3A6T7+KnvinKrjtp1a/AXkCF9hNEx
327             DGbxOYo1UOmk8qdxWCrab34nO+Q8oQc9wjXHG+ZtRYIMoGMKREK8DeL4H1RPNkMf
328             rwXWk8scd8QFmJAb8De1VQ==
329             -----END DSA PRIVATE KEY-----
330              
331             =item * SSH public DSA keys
332              
333             ssh-dss AAAAB3NzaC1kc3MAAACBAKU8/avmk...4XOwuEssAVhmwA==
334              
335             =item * SSH public DSA keys (RFC-4716 format)
336              
337             ---- BEGIN SSH2 PUBLIC KEY ----
338             Comment: "1024-bit DSA, converted from OpenSSH"
339             AAAAB3NzaC1kc3MAAACBAKU8/avmkFeGnSqwYG7dZnQlG+01QNaxu3F5v0NcL/SRUW7Idp
340             Uq8t14siK0mA6yjphLhOf5t8gugTEVBllP86ANSbFigH7WN3v6ydJWqm60pNhNHN//50cn
341             NtIsXbxeq3VtsI64pkH1OJqeZDHLmu73k4T0EKOzsylSfF/wtVBJAAAAFQChpubLHViwPB
342             +jSvUb8e4THS7PBQAAAIAJD1PMCiTCQa1xyD/NCWOajCufTOIzKAhm6l+nlBVPiKI+262X
343             pYt127Ke4mPL8XJBizoTjSQN08uHMg/8L6W/cdO2aZ+mhkBnS1xAm83DAwqLrDraR1w/4Q
344             RFxr5Vbyy8qnejrPjTJobBN1BGsv84wHkjmoCn6pFIfkGYeATlJgAAAIAHYPU1zMVBTDWr
345             u7SNC4G2UyWGWYYLjLytBVHfQmBa51CmqrSs2kCfGLGA1ynfYENsxcJq9nsXrb4i17H5BH
346             JFkH0g7BUDpeBeLr8gsK3WgfqWwtZsDkltObw9chUD/siK6q/dk/fSIB2Ho0inev7k68Z5
347             ZkNI4XOwuEssAVhmwA==
348             ---- END SSH2 PUBLIC KEY ----
349              
350             =back
351              
352             =head2 export_key_der
353              
354             Returns the key as a binary DER-encoded string.
355              
356             my $private_der = $pk->export_key_der('private');
357             #or
358             my $public_der = $pk->export_key_der('public');
359              
360             =head2 export_key_pem
361              
362             Returns the key as a PEM-encoded string (ASCII).
363              
364             my $private_pem = $pk->export_key_pem('private');
365             #or
366             my $public_pem = $pk->export_key_pem('public');
367             #or
368             my $public_pem = $pk->export_key_pem('public_x509');
369              
370             With parameter C<'public'> uses header and footer lines:
371              
372             -----BEGIN DSA PUBLIC KEY------
373             -----END DSA PUBLIC KEY------
374              
375             With parameter C<'public_x509'> uses header and footer lines:
376              
377             -----BEGIN PUBLIC KEY------
378             -----END PUBLIC KEY------
379              
380             Support for password protected PEM keys
381              
382             my $private_pem = $pk->export_key_pem('private', $password);
383             #or
384             my $private_pem = $pk->export_key_pem('private', $password, $cipher);
385              
386             # supported ciphers: 'DES-CBC'
387             # 'DES-EDE3-CBC'
388             # 'SEED-CBC'
389             # 'CAMELLIA-128-CBC'
390             # 'CAMELLIA-192-CBC'
391             # 'CAMELLIA-256-CBC'
392             # 'AES-128-CBC'
393             # 'AES-192-CBC'
394             # 'AES-256-CBC' (DEFAULT)
395              
396             =head2 encrypt
397              
398             Returns the ciphertext as a binary string.
399              
400             DSA is usually used for signatures. This helper is available because the
401             underlying library exposes a DSA-based encryption primitive.
402              
403             my $pk = Crypt::PK::DSA->new($pub_key_filename);
404             my $ct = $pk->encrypt($message);
405             #or
406             my $ct = $pk->encrypt($message, $hash_name);
407              
408             # $hash_name .. [string] 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
409              
410             =head2 decrypt
411              
412             Returns the plaintext as a binary string.
413              
414             my $pk = Crypt::PK::DSA->new($priv_key_filename);
415             my $pt = $pk->decrypt($ciphertext);
416              
417             =head2 sign_message
418              
419             Returns the signature as a binary string.
420              
421             my $pk = Crypt::PK::DSA->new($priv_key_filename);
422             my $signature = $pk->sign_message($message);
423             #or
424             my $signature = $pk->sign_message($message, $hash_name);
425              
426             # $hash_name .. [string] 'SHA1' (DEFAULT, INSECURE), 'SHA256' or any other hash supported by Crypt::Digest
427              
428             B The C<$hash_name> default is C<'SHA1'> only for backward compatibility.
429             SHA-1 is vulnerable to practical collision attacks and is not safe for signing
430             messages whose content may be influenced by an attacker. Always pass an explicit
431             hash name such as C<'SHA256'>. The same applies to L.
432              
433             =head2 verify_message
434              
435             Returns C<1> if the signature is valid, C<0> otherwise.
436              
437             my $pk = Crypt::PK::DSA->new($pub_key_filename);
438             my $valid = $pk->verify_message($signature, $message);
439             #or
440             my $valid = $pk->verify_message($signature, $message, $hash_name);
441              
442             # $hash_name .. [string] 'SHA1' (DEFAULT, INSECURE), 'SHA256' or any other hash supported by Crypt::Digest
443              
444             =head2 sign_hash
445              
446             Returns the signature as a binary string.
447              
448             my $pk = Crypt::PK::DSA->new($priv_key_filename);
449             my $signature = $pk->sign_hash($message_hash);
450              
451             =head2 verify_hash
452              
453             Returns C<1> if the signature is valid, C<0> otherwise.
454              
455             my $pk = Crypt::PK::DSA->new($pub_key_filename);
456             my $valid = $pk->verify_hash($signature, $message_hash);
457              
458             =head2 is_private
459              
460             my $rv = $pk->is_private;
461             # 1 .. private key loaded
462             # 0 .. public key loaded
463             # undef .. no key loaded
464              
465             =head2 size
466              
467             my $size = $pk->size;
468             # returns key size (length of the prime p) in bytes or undef if key not loaded
469              
470             =head2 size_q
471              
472             my $size = $pk->size_q;
473             # returns length of the prime q in bytes or undef if key not loaded
474              
475             =head2 key2hash
476              
477             Returns a hashref with the key components, or C if no key is loaded.
478              
479             my $hash = $pk->key2hash;
480              
481             # returns hash like this (or undef if no key loaded):
482             {
483             type => 1, # integer: 1 .. private, 0 .. public
484             size => 256, # integer: key size in bytes
485             # all the rest are hex strings
486             p => "AAF839A764E04D80824B79FA1F0496C093...", #prime modulus
487             q => "D05C4CB45F29D353442F1FEC43A6BE2BE8...", #prime divisor
488             g => "847E8896D12C9BF18FE283AE7AD58ED7F3...", #generator of a subgroup of order q in GF(p)
489             x => "6C801901AC74E2DC714D75A9F6969483CF...", #private key, random 0 < x < q
490             y => "8F7604D77FA62C7539562458A63C7611B7...", #public key, where y = g^x mod p
491             }
492              
493             =head1 OpenSSL interoperability
494              
495             ### let's have:
496             # DSA private key in PEM format - dsakey.priv.pem
497             # DSA public key in PEM format - dsakey.pub.pem
498             # data file to be signed - input.data
499              
500             =head2 Sign by OpenSSL, verify by Crypt::PK::DSA
501              
502             Create signature (from commandline):
503              
504             openssl dgst -sha256 -sign dsakey.priv.pem -out input.sha256-dsa.sig input.data
505              
506             Verify signature (Perl code):
507              
508             use Crypt::PK::DSA;
509             use Crypt::Digest 'digest_file';
510             use Crypt::Misc 'read_rawfile';
511              
512             my $pkdsa = Crypt::PK::DSA->new("dsakey.pub.pem");
513             my $signature = read_rawfile("input.sha256-dsa.sig");
514             my $valid = $pkdsa->verify_hash($signature, digest_file("SHA256", "input.data"));
515             print $valid ? "SUCCESS" : "FAILURE";
516              
517             =head2 Sign by Crypt::PK::DSA, verify by OpenSSL
518              
519             Create signature (Perl code):
520              
521             use Crypt::PK::DSA;
522             use Crypt::Digest 'digest_file';
523             use Crypt::Misc 'write_rawfile';
524              
525             my $pkdsa = Crypt::PK::DSA->new("dsakey.priv.pem");
526             my $signature = $pkdsa->sign_hash(digest_file("SHA256", "input.data"));
527             write_rawfile("input.sha256-dsa.sig", $signature);
528              
529             Verify signature (from commandline):
530              
531             openssl dgst -sha256 -verify dsakey.pub.pem -signature input.sha256-dsa.sig input.data
532              
533             =head2 Keys generated by Crypt::PK::DSA
534              
535             Generate keys (Perl code):
536              
537             use Crypt::PK::DSA;
538             use Crypt::Misc 'write_rawfile';
539              
540             my $pkdsa = Crypt::PK::DSA->new;
541             $pkdsa->generate_key(20, 128);
542             write_rawfile("dsakey.pub.der", $pkdsa->export_key_der('public'));
543             write_rawfile("dsakey.priv.der", $pkdsa->export_key_der('private'));
544             write_rawfile("dsakey.pub.pem", $pkdsa->export_key_pem('public_x509'));
545             write_rawfile("dsakey.priv.pem", $pkdsa->export_key_pem('private'));
546             write_rawfile("dsakey-passwd.priv.pem", $pkdsa->export_key_pem('private', 'secret'));
547              
548             Use keys by OpenSSL:
549              
550             openssl dsa -in dsakey.priv.der -text -inform der
551             openssl dsa -in dsakey.priv.pem -text
552             openssl dsa -in dsakey-passwd.priv.pem -text -inform pem -passin pass:secret
553             openssl dsa -in dsakey.pub.der -pubin -text -inform der
554             openssl dsa -in dsakey.pub.pem -pubin -text
555              
556             =head2 Keys generated by OpenSSL
557              
558             Generate keys:
559              
560             openssl dsaparam -genkey -out dsakey.priv.pem 1024
561             openssl dsa -in dsakey.priv.pem -out dsakey.priv.der -outform der
562             openssl dsa -in dsakey.priv.pem -out dsakey.pub.pem -pubout
563             openssl dsa -in dsakey.priv.pem -out dsakey.pub.der -outform der -pubout
564             openssl dsa -in dsakey.priv.pem -passout pass:secret -des3 -out dsakey-passwd.priv.pem
565              
566             Load keys (Perl code):
567              
568             use Crypt::PK::DSA;
569              
570             my $pkdsa = Crypt::PK::DSA->new;
571             $pkdsa->import_key("dsakey.pub.der");
572             $pkdsa->import_key("dsakey.priv.der");
573             $pkdsa->import_key("dsakey.pub.pem");
574             $pkdsa->import_key("dsakey.priv.pem");
575             $pkdsa->import_key("dsakey-passwd.priv.pem", "secret");
576              
577             =head1 SEE ALSO
578              
579             =over
580              
581             =item * L
582              
583             =back
584              
585             =cut