File Coverage

blib/lib/Crypt/PK/DSA.pm
Criterion Covered Total %
statement 91 99 91.9
branch 46 76 60.5
condition 10 35 28.5
subroutine 17 18 94.4
pod 10 10 100.0
total 174 238 73.1


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