File Coverage

blib/lib/Crypt/PK/DSA.pm
Criterion Covered Total %
statement 94 99 94.9
branch 47 76 61.8
condition 17 47 36.1
subroutine 17 18 94.4
pod 10 10 100.0
total 185 250 74.0


line stmt bran cond sub pod time code
1             package Crypt::PK::DSA;
2              
3 5     5   111019 use strict;
  5         26  
  5         129  
4 5     5   21 use warnings;
  5         9  
  5         532  
5             our $VERSION = '0.080';
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 5     5   29 use Carp;
  5         9  
  5         297  
13             $Carp::Internal{(__PACKAGE__)}++;
14 5     5   652 use CryptX;
  5         8  
  5         129  
15 5     5   677 use Crypt::Digest 'digest_data';
  5         10  
  5         256  
16 5     5   658 use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64 pem_to_der der_to_pem);
  5         9  
  5         315  
17 5     5   884 use Crypt::PK;
  5         10  
  5         6195  
18              
19             sub new {
20 72     72 1 184627 my $self = shift->_new();
21 72 100       990 return @_ > 0 ? $self->import_key(@_) : $self;
22             }
23              
24             sub generate_key {
25 4     4 1 33 my $self = shift;
26 4 100       518664 return $self->_generate_key_size(@_) if @_ == 2;
27 3 100 66     31 if (@_ == 1 && ref $_[0] eq 'HASH') {
    50 33        
28 1         4 my $param = shift;
29 1 50       4 my $p = $param->{p} or croak "FATAL: 'p' param not specified";
30 1 50       4 my $q = $param->{q} or croak "FATAL: 'q' param not specified";
31 1 50       2 my $g = $param->{g} or croak "FATAL: 'g' param not specified";
32 1         3 $p =~ s/^0x//;
33 1         2 $q =~ s/^0x//;
34 1         3 $g =~ s/^0x//;
35 1         633 return $self->_generate_key_pqg_hex($p, $q, $g);
36             }
37             elsif (@_ == 1 && ref $_[0] eq 'SCALAR') {
38 2         3 my $data = ${$_[0]};
  2         6  
39 2 100       13 if ($data =~ /-----BEGIN DSA PARAMETERS-----\s*(.+)\s*-----END DSA PARAMETERS-----/s) {
40 1 50       5 $data = pem_to_der($data) or croak "FATAL: PEM/params decode failed";
41             }
42 2         5682 return $self->_generate_key_dsaparam($data);
43             }
44 0         0 croak "FATAL: DSA generate_key - invalid args";
45             }
46              
47             sub export_key_pem {
48 8     8 1 3916 my ($self, $type, $password, $cipher) = @_;
49 8   50     347 my $key = $self->export_key_der($type||'');
50 8 50       21 return unless $key;
51 8 100       34 return der_to_pem($key, "DSA PRIVATE KEY", $password, $cipher) if $type eq 'private';
52 4 50       17 return der_to_pem($key, "DSA PUBLIC KEY") if $type eq 'public';
53 0 0       0 return der_to_pem($key, "PUBLIC KEY") if $type eq 'public_x509';
54             }
55              
56             sub import_key {
57 73     73 1 13915 my ($self, $key, $password) = @_;
58 73 50       170 croak "FATAL: undefined key" unless $key;
59              
60             # special case
61 73 100       188 if (ref($key) eq 'HASH') {
62 2 50 33     19 if ($key->{p} && $key->{q} && $key->{g} && $key->{y}) {
      33        
      33        
63             # hash exported via key2hash
64 2         1636 return $self->_import_hex($key->{p}, $key->{q}, $key->{g}, $key->{x}, $key->{y});
65             }
66             }
67              
68 71         96 my $data;
69 71 100       570 if (ref($key) eq 'SCALAR') {
    50          
70 36         67 $data = $$key;
71             }
72             elsif (-f $key) {
73 35         125 $data = read_rawfile($key);
74             }
75             else {
76 0         0 croak "FATAL: non-existing file '$key'";
77             }
78 71 50       192 croak "FATAL: invalid key data" unless $data;
79              
80 71 100       447 if ($data =~ /-----BEGIN (DSA PRIVATE|DSA PUBLIC|PRIVATE|PUBLIC) KEY-----(.*?)-----END/sg) {
    100          
    100          
81 17 50       48 $data = pem_to_der($data, $password) or croak "FATAL: PEM/key decode failed";
82 17         23602 return $self->_import($data);
83             }
84             elsif ($data =~ /---- BEGIN SSH2 PUBLIC KEY ----(.*?)---- END SSH2 PUBLIC KEY ----/sg) {
85 1 50       4 $data = pem_to_der($data) or croak "FATAL: PEM/key decode failed";
86 1         3 my ($typ, $p, $q, $g, $y) = Crypt::PK::_ssh_parse($data);
87 1 50 33     699 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        
88             }
89             elsif ($data =~ /ssh-dss\s+(\S+)/) {
90 1         10 $data = decode_b64("$1");
91 1         6 my ($typ, $p, $q, $g, $y) = Crypt::PK::_ssh_parse($data);
92 1 50 33     714 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        
93             }
94             else {
95 52         163007 return $self->_import($data);
96             }
97 0         0 croak "FATAL: invalid or unsupported DSA key format";
98             }
99              
100             ### FUNCTIONS
101              
102             sub dsa_encrypt {
103 1     1 1 338 my $key = shift;
104 1         7 local $SIG{__DIE__} = \&CryptX::_croak;
105 1 50       8 $key = __PACKAGE__->new($key) unless ref $key;
106 1 50       9 carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
107 1         2587 return $key->encrypt(@_);
108             }
109              
110             sub dsa_decrypt {
111 1     1 1 587 my $key = shift;
112 1         6 local $SIG{__DIE__} = \&CryptX::_croak;
113 1 50       10 $key = __PACKAGE__->new($key) unless ref $key;
114 1 50       8 carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
115 1         1325 return $key->decrypt(@_);
116             }
117              
118             sub dsa_sign_message {
119 1     1 1 398 my $key = shift;
120 1         6 local $SIG{__DIE__} = \&CryptX::_croak;
121 1 50       20 $key = __PACKAGE__->new($key) unless ref $key;
122 1 50       7 carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
123 1         1317 return $key->sign_message(@_);
124             }
125              
126             sub dsa_verify_message {
127 1     1 1 370 my $key = shift;
128 1         6 local $SIG{__DIE__} = \&CryptX::_croak;
129 1 50       7 $key = __PACKAGE__->new($key) unless ref $key;
130 1 50       8 carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
131 1         2559 return $key->verify_message(@_);
132             }
133              
134             sub dsa_sign_hash {
135 1     1 1 15 my $key = shift;
136 1         5 local $SIG{__DIE__} = \&CryptX::_croak;
137 1 50       14 $key = __PACKAGE__->new($key) unless ref $key;
138 1 50       7 carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
139 1         1313 return $key->sign_hash(@_);
140             }
141              
142             sub dsa_verify_hash {
143 1     1 1 406 my $key = shift;
144 1         6 local $SIG{__DIE__} = \&CryptX::_croak;
145 1 50       8 $key = __PACKAGE__->new($key) unless ref $key;
146 1 50       8 carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
147 1         2587 return $key->verify_hash(@_);
148             }
149              
150 0     0     sub CLONE_SKIP { 1 } # prevent cloning
151              
152             1;
153              
154             =pod
155              
156             =head1 NAME
157              
158             Crypt::PK::DSA - Public key cryptography based on DSA
159              
160             =head1 SYNOPSIS
161              
162             ### OO interface
163              
164             #Encryption: Alice
165             my $pub = Crypt::PK::DSA->new('Bob_pub_dsa1.der');
166             my $ct = $pub->encrypt("secret message");
167             #
168             #Encryption: Bob (received ciphertext $ct)
169             my $priv = Crypt::PK::DSA->new('Bob_priv_dsa1.der');
170             my $pt = $priv->decrypt($ct);
171              
172             #Signature: Alice
173             my $priv = Crypt::PK::DSA->new('Alice_priv_dsa1.der');
174             my $sig = $priv->sign_message($message);
175             #
176             #Signature: Bob (received $message + $sig)
177             my $pub = Crypt::PK::DSA->new('Alice_pub_dsa1.der');
178             $pub->verify_message($sig, $message) or die "ERROR";
179              
180             #Key generation
181             my $pk = Crypt::PK::DSA->new();
182             $pk->generate_key(30, 256);
183             my $private_der = $pk->export_key_der('private');
184             my $public_der = $pk->export_key_der('public');
185             my $private_pem = $pk->export_key_pem('private');
186             my $public_pem = $pk->export_key_pem('public');
187              
188             ### Functional interface
189              
190             #Encryption: Alice
191             my $ct = dsa_encrypt('Bob_pub_dsa1.der', "secret message");
192             #Encryption: Bob (received ciphertext $ct)
193             my $pt = dsa_decrypt('Bob_priv_dsa1.der', $ct);
194              
195             #Signature: Alice
196             my $sig = dsa_sign_message('Alice_priv_dsa1.der', $message);
197             #Signature: Bob (received $message + $sig)
198             dsa_verify_message('Alice_pub_dsa1.der', $sig, $message) or die "ERROR";
199              
200             =head1 METHODS
201              
202             =head2 new
203              
204             my $pk = Crypt::PK::DSA->new();
205             #or
206             my $pk = Crypt::PK::DSA->new($priv_or_pub_key_filename);
207             #or
208             my $pk = Crypt::PK::DSA->new(\$buffer_containing_priv_or_pub_key);
209              
210             Support for password protected PEM keys
211              
212             my $pk = Crypt::PK::DSA->new($priv_pem_key_filename, $password);
213             #or
214             my $pk = Crypt::PK::DSA->new(\$buffer_containing_priv_pem_key, $password);
215              
216             =head2 generate_key
217              
218             Uses Yarrow-based cryptographically strong random number generator seeded with
219             random data taken from C (UNIX) or C (Win32).
220              
221             $pk->generate_key($group_size, $modulus_size);
222             # $group_size ... in bytes .. 15 < $group_size < 1024
223             # $modulus_size .. in bytes .. ($modulus_size - $group_size) < 512
224              
225             ### Bits of Security according to libtomcrypt documentation
226             # 80 bits => generate_key(20, 128)
227             # 120 bits => generate_key(30, 256)
228             # 140 bits => generate_key(35, 384)
229             # 160 bits => generate_key(40, 512)
230              
231             ### Sizes according section 4.2 of FIPS 186-4
232             # (L and N are the bit lengths of p and q respectively)
233             # L = 1024, N = 160 => generate_key(20, 128)
234             # L = 2048, N = 224 => generate_key(28, 256)
235             # L = 2048, N = 256 => generate_key(32, 256)
236             # L = 3072, N = 256 => generate_key(32, 384)
237              
238             $pk->generate_key($param_hash)
239             # $param_hash is { d => $d, p => $p, q => $q }
240             # where $d, $p, $q are hex strings
241              
242             $pk->generate_key(\$dsa_param)
243             # $dsa_param is the content of DER or PEM file with DSA params
244             # e.g. openssl dsaparam 2048
245              
246             =head2 import_key
247              
248             Loads private or public key in DER or PEM format.
249              
250             $pk->import_key($filename);
251             #or
252             $pk->import_key(\$buffer_containing_key);
253              
254             Support for password protected PEM keys
255              
256             $pk->import_key($pem_filename, $password);
257             #or
258             $pk->import_key(\$buffer_containing_pem_key, $password);
259              
260             Loading private or public keys form perl hash:
261              
262             $pk->import_key($hashref);
263              
264             # where $hashref is a key exported via key2hash
265             $pk->import_key({
266             p => "AAF839A764E04D80824B79FA1F0496C093...", #prime modulus
267             q => "D05C4CB45F29D353442F1FEC43A6BE2BE8...", #prime divisor
268             g => "847E8896D12C9BF18FE283AE7AD58ED7F3...", #generator of a subgroup of order q in GF(p)
269             x => "6C801901AC74E2DC714D75A9F6969483CF...", #private key, random 0 < x < q
270             y => "8F7604D77FA62C7539562458A63C7611B7...", #public key, where y = g^x mod p
271             });
272              
273             Supported key formats:
274              
275             =over
276              
277             =item * DSA public keys
278              
279             -----BEGIN PUBLIC KEY-----
280             MIIBtjCCASsGByqGSM44BAEwggEeAoGBAJKyu+puNMGLpGIhbD1IatnwlI79ePr4
281             YHe2KBhRkheKxWUZRpN1Vd/+usS2IHSJ9op5cSWETiP05d7PMtJaitklw7jhudq3
282             GxNvV/GRdCQm3H6d76FHP88dms4vcDYc6ry6wKERGfNEtZ+4BAKrMZK+gDYsF4Aw
283             U6WVR969kYZhAhUA6w25FgSRmJ8W4XkvC60n8Wv3DpMCgYA4ZFE+3tLOM24PZj9Z
284             rxuqUzZZdR+kIzrsIYpWN9ustbmdKLKwsqIaUIxc5zxHEhbAjAIf8toPD+VEQIpY
285             7vgJgDhXuPq45BgN19iLTzOJwIhAFXPZvnAdIo9D/AnMw688gT6g6U8QCZwX2XYg
286             ICiVcriYVNcjVKHSFY/X0Oi7CgOBhAACgYB4ZTn4OYT/pjUd6tNhGPtOS3CE1oaj
287             5ScbetXg4ZDpceEyQi8VG+/ZTbs8var8X77JdEdeQA686cAxpOaVgW8V4odvcmfA
288             BfueiGnPXjqGfppiHAyL1Ngyd+EsXKmKVXZYAVFVI0WuJKiZBSVURU7+ByxOfpGa
289             fZhibr0SggWixQ==
290             -----END PUBLIC KEY-----
291              
292             =item * DSA private keys
293              
294             -----BEGIN DSA PRIVATE KEY-----
295             MIIBuwIBAAKBgQCSsrvqbjTBi6RiIWw9SGrZ8JSO/Xj6+GB3tigYUZIXisVlGUaT
296             dVXf/rrEtiB0ifaKeXElhE4j9OXezzLSWorZJcO44bnatxsTb1fxkXQkJtx+ne+h
297             Rz/PHZrOL3A2HOq8usChERnzRLWfuAQCqzGSvoA2LBeAMFOllUfevZGGYQIVAOsN
298             uRYEkZifFuF5LwutJ/Fr9w6TAoGAOGRRPt7SzjNuD2Y/Wa8bqlM2WXUfpCM67CGK
299             VjfbrLW5nSiysLKiGlCMXOc8RxIWwIwCH/LaDw/lRECKWO74CYA4V7j6uOQYDdfY
300             i08zicCIQBVz2b5wHSKPQ/wJzMOvPIE+oOlPEAmcF9l2ICAolXK4mFTXI1Sh0hWP
301             19DouwoCgYB4ZTn4OYT/pjUd6tNhGPtOS3CE1oaj5ScbetXg4ZDpceEyQi8VG+/Z
302             Tbs8var8X77JdEdeQA686cAxpOaVgW8V4odvcmfABfueiGnPXjqGfppiHAyL1Ngy
303             d+EsXKmKVXZYAVFVI0WuJKiZBSVURU7+ByxOfpGafZhibr0SggWixQIVAL7Sia03
304             8bvANjjL9Sitk8slrM6P
305             -----END DSA PRIVATE KEY-----
306              
307             =item * DSA private keys in password protected PEM format:
308              
309             -----BEGIN DSA PRIVATE KEY-----
310             Proc-Type: 4,ENCRYPTED
311             DEK-Info: DES-CBC,227ADC3AA0299491
312              
313             UISxBYAxPQMl2eK9LMAeHsssF6IxO+4G2ta2Jn8VE+boJrrH3iSTKeMXGjGaXl0z
314             DwcLGV+KMR70y+cxtTb34rFy+uSpBy10dOQJhxALDbe1XfCDQIUfaXRfMNA3um2I
315             JdZixUD/zcxBOUzao+MCr0V9XlJDgqBhJ5EEr53XHH07Eo5fhiBfbbR9NzdUPFrQ
316             p2ASyZtFh7RXoIBUCQgg21oeLddcNWV7gd/Y46kghO9s0JbJ8C+IsuWEPRSq502h
317             tSoDN6B0sxbVvOUICLLbQaxt7yduTAhRxVIJZ1PWATTVD7CZBVz9uIDZ7LOv+er2
318             1q3vkwb8E9spPsA240+BnfD571XEop4jrawxC0VKQZ+3cPVLc6jhIsxvzzFQUt67
319             g66v8GUgt7KF3KhVV7qEtntybQWDWb+K/uTIH9Ra8nP820d3Rnl61pPXDPlluteT
320             WSLOvEMN2zRmkaxQNv/tLdT0SYpQtdjw74G3A6T7+KnvinKrjtp1a/AXkCF9hNEx
321             DGbxOYo1UOmk8qdxWCrab34nO+Q8oQc9wjXHG+ZtRYIMoGMKREK8DeL4H1RPNkMf
322             rwXWk8scd8QFmJAb8De1VQ==
323             -----END DSA PRIVATE KEY-----
324              
325             =item * SSH public DSA keys
326              
327             ssh-dss AAAAB3NzaC1kc3MAAACBAKU8/avmk...4XOwuEssAVhmwA==
328              
329             =item * SSH public DSA keys (RFC-4716 format)
330              
331             ---- BEGIN SSH2 PUBLIC KEY ----
332             Comment: "1024-bit DSA, converted from OpenSSH"
333             AAAAB3NzaC1kc3MAAACBAKU8/avmkFeGnSqwYG7dZnQlG+01QNaxu3F5v0NcL/SRUW7Idp
334             Uq8t14siK0mA6yjphLhOf5t8gugTEVBllP86ANSbFigH7WN3v6ydJWqm60pNhNHN//50cn
335             NtIsXbxeq3VtsI64pkH1OJqeZDHLmu73k4T0EKOzsylSfF/wtVBJAAAAFQChpubLHViwPB
336             +jSvUb8e4THS7PBQAAAIAJD1PMCiTCQa1xyD/NCWOajCufTOIzKAhm6l+nlBVPiKI+262X
337             pYt127Ke4mPL8XJBizoTjSQN08uHMg/8L6W/cdO2aZ+mhkBnS1xAm83DAwqLrDraR1w/4Q
338             RFxr5Vbyy8qnejrPjTJobBN1BGsv84wHkjmoCn6pFIfkGYeATlJgAAAIAHYPU1zMVBTDWr
339             u7SNC4G2UyWGWYYLjLytBVHfQmBa51CmqrSs2kCfGLGA1ynfYENsxcJq9nsXrb4i17H5BH
340             JFkH0g7BUDpeBeLr8gsK3WgfqWwtZsDkltObw9chUD/siK6q/dk/fSIB2Ho0inev7k68Z5
341             ZkNI4XOwuEssAVhmwA==
342             ---- END SSH2 PUBLIC KEY ----
343              
344             =back
345              
346             =head2 export_key_der
347              
348             my $private_der = $pk->export_key_der('private');
349             #or
350             my $public_der = $pk->export_key_der('public');
351              
352             =head2 export_key_pem
353              
354             my $private_pem = $pk->export_key_pem('private');
355             #or
356             my $public_pem = $pk->export_key_pem('public');
357             #or
358             my $public_pem = $pk->export_key_pem('public_x509');
359              
360             With parameter C<'public'> uses header and footer lines:
361              
362             -----BEGIN DSA PUBLIC KEY------
363             -----END DSA PUBLIC KEY------
364              
365             With parameter C<'public_x509'> uses header and footer lines:
366              
367             -----BEGIN PUBLIC KEY------
368             -----END PUBLIC KEY------
369              
370             Support for password protected PEM keys
371              
372             my $private_pem = $pk->export_key_pem('private', $password);
373             #or
374             my $private_pem = $pk->export_key_pem('private', $password, $cipher);
375              
376             # supported ciphers: 'DES-CBC'
377             # 'DES-EDE3-CBC'
378             # 'SEED-CBC'
379             # 'CAMELLIA-128-CBC'
380             # 'CAMELLIA-192-CBC'
381             # 'CAMELLIA-256-CBC'
382             # 'AES-128-CBC'
383             # 'AES-192-CBC'
384             # 'AES-256-CBC' (DEFAULT)
385              
386             =head2 encrypt
387              
388             my $pk = Crypt::PK::DSA->new($pub_key_filename);
389             my $ct = $pk->encrypt($message);
390             #or
391             my $ct = $pk->encrypt($message, $hash_name);
392              
393             #NOTE: $hash_name can be 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
394              
395             =head2 decrypt
396              
397             my $pk = Crypt::PK::DSA->new($priv_key_filename);
398             my $pt = $pk->decrypt($ciphertext);
399              
400             =head2 sign_message
401              
402             my $pk = Crypt::PK::DSA->new($priv_key_filename);
403             my $signature = $priv->sign_message($message);
404             #or
405             my $signature = $priv->sign_message($message, $hash_name);
406              
407             #NOTE: $hash_name can be 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
408              
409             =head2 verify_message
410              
411             my $pk = Crypt::PK::DSA->new($pub_key_filename);
412             my $valid = $pub->verify_message($signature, $message)
413             #or
414             my $valid = $pub->verify_message($signature, $message, $hash_name);
415              
416             #NOTE: $hash_name can be 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
417              
418             =head2 sign_hash
419              
420             my $pk = Crypt::PK::DSA->new($priv_key_filename);
421             my $signature = $priv->sign_hash($message_hash);
422              
423             =head2 verify_hash
424              
425             my $pk = Crypt::PK::DSA->new($pub_key_filename);
426             my $valid = $pub->verify_hash($signature, $message_hash);
427              
428             =head2 is_private
429              
430             my $rv = $pk->is_private;
431             # 1 .. private key loaded
432             # 0 .. public key loaded
433             # undef .. no key loaded
434              
435             =head2 size
436              
437             my $size = $pk->size;
438             # returns key size (length of the prime p) in bytes or undef if key not loaded
439              
440             =head2 size_q
441              
442             my $size = $pk->size_q;
443             # returns length of the prime q in bytes or undef if key not loaded
444              
445             =head2 key2hash
446              
447             my $hash = $pk->key2hash;
448              
449             # returns hash like this (or undef if no key loaded):
450             {
451             type => 1, # integer: 1 .. private, 0 .. public
452             size => 256, # integer: key size in bytes
453             # all the rest are hex strings
454             p => "AAF839A764E04D80824B79FA1F0496C093...", #prime modulus
455             q => "D05C4CB45F29D353442F1FEC43A6BE2BE8...", #prime divisor
456             g => "847E8896D12C9BF18FE283AE7AD58ED7F3...", #generator of a subgroup of order q in GF(p)
457             x => "6C801901AC74E2DC714D75A9F6969483CF...", #private key, random 0 < x < q
458             y => "8F7604D77FA62C7539562458A63C7611B7...", #public key, where y = g^x mod p
459             }
460              
461             =head1 FUNCTIONS
462              
463             =head2 dsa_encrypt
464              
465             DSA based encryption as implemented by libtomcrypt. See method L below.
466              
467             my $ct = dsa_encrypt($pub_key_filename, $message);
468             #or
469             my $ct = dsa_encrypt(\$buffer_containing_pub_key, $message);
470             #or
471             my $ct = dsa_encrypt($pub_key_filename, $message, $hash_name);
472              
473             #NOTE: $hash_name can be 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
474              
475             Encryption works similar to the L encryption whereas shared DSA key is computed, and
476             the hash of the shared key XOR'ed against the plaintext forms the ciphertext.
477              
478             =head2 dsa_decrypt
479              
480             DSA based decryption as implemented by libtomcrypt. See method L below.
481              
482             my $pt = dsa_decrypt($priv_key_filename, $ciphertext);
483             #or
484             my $pt = dsa_decrypt(\$buffer_containing_priv_key, $ciphertext);
485              
486             =head2 dsa_sign_message
487              
488             Generate DSA signature. See method L below.
489              
490             my $sig = dsa_sign_message($priv_key_filename, $message);
491             #or
492             my $sig = dsa_sign_message(\$buffer_containing_priv_key, $message);
493             #or
494             my $sig = dsa_sign_message($priv_key, $message, $hash_name);
495              
496             =head2 dsa_verify_message
497              
498             Verify DSA signature. See method L below.
499              
500             dsa_verify_message($pub_key_filename, $signature, $message) or die "ERROR";
501             #or
502             dsa_verify_message(\$buffer_containing_pub_key, $signature, $message) or die "ERROR";
503             #or
504             dsa_verify_message($pub_key, $signature, $message, $hash_name) or die "ERROR";
505              
506             =head2 dsa_sign_hash
507              
508             Generate DSA signature. See method L below.
509              
510             my $sig = dsa_sign_hash($priv_key_filename, $message_hash);
511             #or
512             my $sig = dsa_sign_hash(\$buffer_containing_priv_key, $message_hash);
513              
514             =head2 dsa_verify_hash
515              
516             Verify DSA signature. See method L below.
517              
518             dsa_verify_hash($pub_key_filename, $signature, $message_hash) or die "ERROR";
519             #or
520             dsa_verify_hash(\$buffer_containing_pub_key, $signature, $message_hash) or die "ERROR";
521              
522             =head1 OpenSSL interoperability
523              
524             ### let's have:
525             # DSA private key in PEM format - dsakey.priv.pem
526             # DSA public key in PEM format - dsakey.pub.pem
527             # data file to be signed - input.data
528              
529             =head2 Sign by OpenSSL, verify by Crypt::PK::DSA
530              
531             Create signature (from commandline):
532              
533             openssl dgst -sha1 -sign dsakey.priv.pem -out input.sha1-dsa.sig input.data
534              
535             Verify signature (Perl code):
536              
537             use Crypt::PK::DSA;
538             use Crypt::Digest 'digest_file';
539             use Crypt::Misc 'read_rawfile';
540              
541             my $pkdsa = Crypt::PK::DSA->new("dsakey.pub.pem");
542             my $signature = read_rawfile("input.sha1-dsa.sig");
543             my $valid = $pkdsa->verify_hash($signature, digest_file("SHA1", "input.data"), "SHA1", "v1.5");
544             print $valid ? "SUCCESS" : "FAILURE";
545              
546             =head2 Sign by Crypt::PK::DSA, verify by OpenSSL
547              
548             Create signature (Perl code):
549              
550             use Crypt::PK::DSA;
551             use Crypt::Digest 'digest_file';
552             use Crypt::Misc 'write_rawfile';
553              
554             my $pkdsa = Crypt::PK::DSA->new("dsakey.priv.pem");
555             my $signature = $pkdsa->sign_hash(digest_file("SHA1", "input.data"), "SHA1", "v1.5");
556             write_rawfile("input.sha1-dsa.sig", $signature);
557              
558             Verify signature (from commandline):
559              
560             openssl dgst -sha1 -verify dsakey.pub.pem -signature input.sha1-dsa.sig input.data
561              
562             =head2 Keys generated by Crypt::PK::DSA
563              
564             Generate keys (Perl code):
565              
566             use Crypt::PK::DSA;
567             use Crypt::Misc 'write_rawfile';
568              
569             my $pkdsa = Crypt::PK::DSA->new;
570             $pkdsa->generate_key(20, 128);
571             write_rawfile("dsakey.pub.der", $pkdsa->export_key_der('public'));
572             write_rawfile("dsakey.priv.der", $pkdsa->export_key_der('private'));
573             write_rawfile("dsakey.pub.pem", $pkdsa->export_key_pem('public_x509'));
574             write_rawfile("dsakey.priv.pem", $pkdsa->export_key_pem('private'));
575             write_rawfile("dsakey-passwd.priv.pem", $pkdsa->export_key_pem('private', 'secret'));
576              
577             Use keys by OpenSSL:
578              
579             openssl dsa -in dsakey.priv.der -text -inform der
580             openssl dsa -in dsakey.priv.pem -text
581             openssl dsa -in dsakey-passwd.priv.pem -text -inform pem -passin pass:secret
582             openssl dsa -in dsakey.pub.der -pubin -text -inform der
583             openssl dsa -in dsakey.pub.pem -pubin -text
584              
585             =head2 Keys generated by OpenSSL
586              
587             Generate keys:
588              
589             openssl dsaparam -genkey -out dsakey.priv.pem 1024
590             openssl dsa -in dsakey.priv.pem -out dsakey.priv.der -outform der
591             openssl dsa -in dsakey.priv.pem -out dsakey.pub.pem -pubout
592             openssl dsa -in dsakey.priv.pem -out dsakey.pub.der -outform der -pubout
593             openssl dsa -in dsakey.priv.pem -passout pass:secret -des3 -out dsakey-passwd.priv.pem
594              
595             Load keys (Perl code):
596              
597             use Crypt::PK::DSA;
598              
599             my $pkdsa = Crypt::PK::DSA->new;
600             $pkdsa->import_key("dsakey.pub.der");
601             $pkdsa->import_key("dsakey.priv.der");
602             $pkdsa->import_key("dsakey.pub.pem");
603             $pkdsa->import_key("dsakey.priv.pem");
604             $pkdsa->import_key("dsakey-passwd.priv.pem", "secret");
605              
606             =head1 SEE ALSO
607              
608             =over
609              
610             =item * L
611              
612             =back
613              
614             =cut