File Coverage

blib/lib/Authen/Passphrase.pm
Criterion Covered Total %
statement 24 46 52.1
branch 2 24 8.3
condition n/a
subroutine 9 9 100.0
pod 3 3 100.0
total 38 82 46.3


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Authen::Passphrase - hashed passwords/passphrases as objects
4              
5             =head1 SYNOPSIS
6              
7             use Authen::Passphrase;
8              
9             $ppr = Authen::Passphrase->from_crypt($passwd);
10             $ppr = Authen::Passphrase->from_rfc2307($userPassword);
11              
12             if($ppr->match($passphrase)) { ...
13              
14             $passphrase = $ppr->passphrase;
15              
16             $crypt = $ppr->as_crypt;
17             $userPassword = $ppr->as_rfc2307;
18              
19             =head1 DESCRIPTION
20              
21             B. For a module that's more extensible, and
22             less held-back by legacy algorithms, you may want to use
23             L instead.
24              
25             This is the base class for a system of objects that encapsulate
26             passphrases. An object of this type is a passphrase recogniser: its
27             job is to recognise whether an offered passphrase is the right one.
28             For security, such passphrase recognisers usually do not themselves know
29             the passphrase they are looking for; they can merely recognise it when
30             they see it. There are many schemes in use to achieve this effect,
31             and the intent of this class is to provide a consistent interface to
32             them all, hiding the details.
33              
34             The CPAN package Authen-Passphrase contains implementations of several
35             specific passphrase schemes in addition to the base class. See the
36             specific classes for notes on the security properties of each scheme.
37             In new systems, if there is a choice of which passphrase algorithm to
38             use, it is recommended to use L or
39             L. Most other schemes are too weak
40             for new applications, and should be used only for backward compatibility.
41              
42             =head2 Side-channel cryptanalysis
43              
44             Both the Authen-Passphrase framework and most of the underlying
45             cryptographic algorithm implementations are vulnerable to side-channel
46             cryptanalytic attacks. However, the impact of this is quite limited.
47              
48             Unlike the case of symmetric encryption, where a side-channel attack can
49             extract the plaintext directly, the cryptographic operations involved in
50             passphrase recognition don't directly process the correct passphrase.
51             A sophisticated side-channel attack, applied when offering incorrect
52             passphrases for checking, could potentially extract salt (from the
53             operation of the hashing algorithm) and the target hash value (from
54             the comparison of hash values). This would enable a cryptanalytic or
55             brute-force attack on the passphrase recogniser to be performed offline.
56             This is not a disaster; the very intent of storing only a hash of
57             the correct passphrase is that leakage of these stored values doesn't
58             compromise the passphrase.
59              
60             In a typical usage scenario for this framework, the side-channel attacks
61             that can be mounted are very restricted. If authenticating network
62             users, typically an attacker has no access at all to power consumption,
63             electromagnetic emanation, and other such side channels. The only
64             side channel that is readily available is timing, and the precision of
65             timing measurements is significantly blunted by the normal processes of
66             network communication. For example, it would not normally be feasible
67             to mount a timing attack against hash value comparison (to see how far
68             through the values the first mismatch was).
69              
70             Perl as a whole has not been built as a platform for
71             side-channel-resistant cryptography, so hardening Authen-Passphrase and
72             its underlying algorithms is not feasible. In any serious use of Perl
73             for cryptography, including for authentication using Authen-Passphrase,
74             an analysis should be made of the exposure to side-channel attacks,
75             and if necessary efforts made to further blunt the timing channel.
76              
77             One timing attack that is very obviously feasible over the network is to
78             determine which of several passphrase hashing algorithms is being used.
79             This can potentially distinguish between classes of user accounts,
80             or distinguish between existing and non-existing user accounts when an
81             attacker is guessing usernames. To obscure this information requires
82             an extreme restriction of the timing channel, most likely by explicitly
83             pausing to standardise the amount of time spent on authentication.
84             This defence also rules out essentially all other timing attacks.
85              
86             =head1 PASSPHRASE ENCODINGS
87              
88             Because hashed passphrases frequently need to be stored, various encodings
89             of them have been devised. This class has constructors and methods to
90             support these.
91              
92             =head2 crypt encoding
93              
94             The Unix crypt() function, which performs passphrase hashing, returns
95             hashes in a textual format intended to be stored in a text file.
96             In particular, such hashes are stored in /etc/passwd (and now /etc/shadow)
97             to control access to Unix user accounts. The same textual format has
98             been adopted and extended by other passphrase-handling software such as
99             password crackers.
100              
101             For historical reasons, there are several different syntaxes used in this
102             format. The original DES-based password scheme represents its hashes
103             simply as a string of thirteen base 64 digits. An extended variant of
104             this scheme uses nineteen base 64 digits, preceded by an "B<_>" marker.
105             A more general syntax was developed later, which starts the string with
106             "B<$>", an alphanumeric scheme identifier, and another "B<$>".
107              
108             In addition to actual passphrase hashes, the crypt format can also
109             represent a couple of special cases. The empty string indicates that
110             there is no access control; it is possible to login without giving a
111             passphrase. Finally, any string that is not a possible output of crypt()
112             may be used to prevent login completely; "B<*>" is the usual choice,
113             but other strings are used too.
114              
115             crypt strings are intended to be used in text files that use colon and
116             newline characters as delimiters. This module treats the crypt string
117             syntax as being limited to ASCII graphic characters excluding colon.
118              
119             =head2 RFC 2307 encoding
120              
121             RFC 2307 describes an encoding system for passphrase hashes, to be used
122             in the "B" attribute in LDAP databases. It encodes hashes
123             as ASCII text, and supports several passphrase schemes in an extensible
124             way by starting the encoding with an alphanumeric scheme identifier
125             enclosed in braces. There are several standard scheme identifiers.
126             The "B<{CRYPT}>" scheme allows the use of any crypt encoding.
127              
128             This module treats the RFC 2307 string syntax as being limited to ASCII
129             graphic characters.
130              
131             The RFC 2307 encoding is a good one, and is recommended for storage and
132             exchange of passphrase hashes.
133              
134             =cut
135              
136             package Authen::Passphrase;
137              
138 23     23   397998 { use 5.006; }
  23         76  
139 23     23   143 use warnings;
  23         36  
  23         1049  
140 23     23   235 use strict;
  23         46  
  23         609  
141              
142 23     23   90 use Carp qw(croak);
  23         44  
  23         1571  
143 23     23   8909 use MIME::Base64 2.21 qw(decode_base64);
  23         14883  
  23         1681  
144 23     23   9878 use Module::Runtime 0.011 qw(use_module);
  23         36803  
  23         168  
145              
146             our $VERSION = "0.009";
147              
148             =head1 CONSTRUCTORS
149              
150             =over
151              
152             =item Authen::Passphrase->from_crypt(PASSWD)
153              
154             Returns a passphrase recogniser object matching the supplied crypt
155             encoding. This constructor may only be called on the base class, not
156             any subclass.
157              
158             The specific passphrase recogniser class is loaded at runtime, so
159             successfully loading C does not guarantee that
160             it will be possible to use a specific type of passphrase recogniser.
161             If necessary, check separately for presence and loadability of the
162             recogniser class.
163              
164             Known scheme identifiers:
165              
166             =over
167              
168             =item B<$1$>
169              
170             A baroque passphrase scheme based on MD5, designed by
171             Poul-Henning Kamp and originally implemented in FreeBSD. See
172             L.
173              
174             =item B<$2$>
175              
176             =item B<$2a$>
177              
178             Two versions of a passphrase scheme based on Blowfish,
179             designed by Niels Provos and David Mazieres for OpenBSD. See
180             L.
181              
182             =item B<$3$>
183              
184             The NT-Hash scheme, which stores the MD4 hash of the passphrase expressed
185             in Unicode. See L.
186              
187             =item B<$IPB2$>
188              
189             Invision Power Board 2.x salted MD5
190              
191             =item B<$K4$>
192              
193             Kerberos AFS DES
194              
195             =item B<$LM$>
196              
197             Half of the Microsoft LAN Manager hash scheme. The two
198             halves of a LAN Manager hash can be separated and manipulated
199             independently; this represents such an isolated half. See
200             L.
201              
202             =item B<$NT$>
203              
204             The NT-Hash scheme, which stores the MD4 hash of the passphrase expressed
205             in Unicode. See L.
206              
207             The B<$3$> identifier refers to the same hash algorithm, but has a
208             slightly different textual format (an extra "B<$>").
209              
210             =item B<$P$>
211              
212             Portable PHP password hash (phpass), based on MD5. See
213             L.
214              
215             =item B<$VMS1$>
216              
217             =item B<$VMS2$>
218              
219             =item B<$VMS3$>
220              
221             Three variants of the Purdy polynomial system used in VMS.
222             See L.
223              
224             =item B<$af$>
225              
226             Kerberos v4 TGT
227              
228             =item B<$apr1$>
229              
230             A variant of the B<$1$> scheme, used by Apache.
231              
232             =item B<$krb5$>
233              
234             Kerberos v5 TGT
235              
236             =back
237              
238             The historical formats supported are:
239              
240             =over
241              
242             =item "I"
243              
244             ("I" represents a base 64 digit.) The original DES-based Unix password
245             hash scheme. See L.
246              
247             =item "B<_>I"
248              
249             ("I" represents a base 64 digit.) Extended DES-based passphrase hash
250             scheme from BSDi. See L.
251              
252             =item ""
253              
254             Accept any passphrase. See L.
255              
256             =item "B<*>"
257              
258             To handle historical practice, anything non-empty but shorter than 13
259             characters and not starting with "B<$>" is treated as deliberately
260             rejecting all passphrases. (See L.)
261             Anything 13 characters or longer, or starting with "B<$>", that is not
262             recognised as a hash is treated as an error.
263              
264             =back
265              
266             There are also two different passphrase schemes that use a crypt string
267             consisting of 24 base 64 digits. One is named "bigcrypt" and appears in
268             HP-UX, Digital Unix, and OSF/1 (see L).
269             The other is named "crypt16" and appears in Ultrix and Tru64 (see
270             L). These schemes conflict. Neither of
271             them is accepted as a crypt string by this constructor; such strings
272             are regarded as invalid encodings.
273              
274             =cut
275              
276             my %crypt_scheme_handler = (
277             "1" => [ "Authen::Passphrase::MD5Crypt", 0.003 ],
278             "2" => [ "Authen::Passphrase::BlowfishCrypt", 0.007 ],
279             "2a" => [ "Authen::Passphrase::BlowfishCrypt", 0.007 ],
280             "3" => [ "Authen::Passphrase::NTHash", 0.003 ],
281             "IPB2" => sub($) { croak '$IPB2$ is unimplemented' },
282             "K4" => sub($) { croak '$K4$ is unimplemented' },
283             "LM" => [ "Authen::Passphrase::LANManagerHalf", 0.003 ],
284             "NT" => [ "Authen::Passphrase::NTHash", 0.003 ],
285             "P" => [ "Authen::Passphrase::PHPass", 0.003 ],
286             "VMS1" => [ "Authen::Passphrase::VMSPurdy", 0.006 ],
287             "VMS2" => [ "Authen::Passphrase::VMSPurdy", 0.006 ],
288             "VMS3" => [ "Authen::Passphrase::VMSPurdy", 0.006 ],
289             "af" => sub($) { croak '$af$ is unimplemented' },
290             "apr1" => sub($) { croak '$apr1$ is unimplemented' },
291             "krb5" => sub($) { croak '$krb5$ is unimplemented' },
292             );
293              
294             sub from_crypt {
295 5     5 1 12 my($class, $passwd) = @_;
296 5 50       995 croak "crypt string \"$passwd\" not supported for $class"
297             unless $class eq __PACKAGE__;
298 0         0 my $handler;
299 0 0       0 if($passwd =~ /\A\$([0-9A-Za-z]+)\$/) {
    0          
    0          
    0          
300 0         0 my $scheme = $1;
301 0         0 $handler = $crypt_scheme_handler{$scheme};
302 0 0       0 croak "unrecognised crypt scheme \$$scheme\$"
303             unless defined $handler;
304             } elsif($passwd =~ m#\A(?:[^\$].{12}|_.{19})\z#s) {
305 0         0 $handler = [ "Authen::Passphrase::DESCrypt", 0.006 ];
306             } elsif($passwd eq "") {
307 0         0 $handler = [ "Authen::Passphrase::AcceptAll", 0.003 ];
308             } elsif($passwd =~ /\A[^\$].{0,11}\z/s) {
309 0         0 $handler = [ "Authen::Passphrase::RejectAll", 0.003 ];
310             } else {
311 0         0 croak "bad crypt syntax in \"$passwd\"";
312             }
313 0 0       0 if(ref($handler) eq "CODE") {
314 0         0 return $handler->($passwd);
315             } else {
316 0         0 my($modname, $modver) = @$handler;
317 0         0 return use_module($modname, $modver)->from_crypt($passwd);
318             }
319             }
320              
321             =item Authen::Passphrase->from_rfc2307(USERPASSWORD)
322              
323             Returns a passphrase recogniser object matching the supplied RFC 2307
324             encoding. This constructor may only be called on the base class, not
325             any subclass.
326              
327             The specific passphrase recogniser class is loaded at runtime. See the
328             note about this for the L constructor above.
329              
330             Known scheme identifiers:
331              
332             =over
333              
334             =item B<{CLEARTEXT}>
335              
336             Passphrase stored in cleartext. See L.
337              
338             =item B<{CRYPT}>
339              
340             The scheme identifier is followed by a crypt string.
341              
342             =item B<{CRYPT16}>
343              
344             Used ambiguously by Exim, to refer to either crypt16
345             (see L) or bigcrypt (see
346             L) depending on compilation options.
347             This is a bug, resulting from a confusion between the two algorithms.
348             This module does not support any meaning for this scheme identifier.
349              
350             =item B<{K5KEY}>
351              
352             Not a real passphrase scheme, but a placeholder to indicate that a
353             Kerberos key stored separately should be checked against. No data
354             follows the scheme identifier.
355              
356             =item B<{KERBEROS}>
357              
358             Not a real passphrase scheme, but a placeholder to indicate that
359             Kerberos should be invoked to check against a user's passphrase.
360             The scheme identifier is followed by the user's username, in the form
361             "IB<@>I".
362              
363             =item B<{LANM}>
364              
365             Synonym for B<{LANMAN}>, used by CommuniGate Pro.
366              
367             =item B<{LANMAN}>
368              
369             The Microsoft LAN Manager hash scheme. See
370             L.
371              
372             =item B<{MD4}>
373              
374             The MD4 digest of the passphrase is stored. See
375             L.
376              
377             =item B<{MD5}>
378              
379             The MD5 digest of the passphrase is stored. See
380             L.
381              
382             =item B<{MSNT}>
383              
384             The NT-Hash scheme, which stores the MD4 hash of the passphrase expressed
385             in Unicode. See L.
386              
387             =item B<{NS-MTA-MD5}>
388              
389             An MD5-based scheme used by Netscape Mail Server. See
390             L.
391              
392             =item B<{RMD160}>
393              
394             The RIPEMD-160 digest of the passphrase is stored. See
395             L.
396              
397             =item B<{SASL}>
398              
399             Not a real passphrase scheme, but a placeholder to indicate that SASL
400             should be invoked to check against a user's passphrase. The scheme
401             identifier is followed by the user's username.
402              
403             =item B<{SHA}>
404              
405             The SHA-1 digest of the passphrase is stored. See
406             L.
407              
408             =item B<{SMD5}>
409              
410             The MD5 digest of the passphrase plus a salt is stored. See
411             L.
412              
413             =item B<{SSHA}>
414              
415             The SHA-1 digest of the passphrase plus a salt is stored.
416             See L.
417              
418             =item B<{UNIX}>
419              
420             Not a real passphrase scheme, but a placeholder to indicate that Unix
421             mechanisms should be used to check against a Unix user's login passphrase.
422             The scheme identifier is followed by the user's username.
423              
424             =item B<{WM-CRY}>
425              
426             Synonym for B<{CRYPT}>, used by CommuniGate Pro.
427              
428             =back
429              
430             =cut
431              
432             my %rfc2307_scheme_handler = (
433             "CLEARTEXT" => [ "Authen::Passphrase::Clear", 0.003 ],
434             # "CRYPT" is handled specially
435             "CRYPT16" => sub($) { croak "{CRYPT16} is ambiguous" },
436             "K5KEY" => sub($) { croak "{K5KEY} is a placeholder" },
437             "KERBEROS" => sub($) { croak "{KERBEROS} is a placeholder" },
438             "LANM" => [ "Authen::Passphrase::LANManager", 0.003 ],
439             "LANMAN" => [ "Authen::Passphrase::LANManager", 0.003 ],
440             "MD4" => [ "Authen::Passphrase::SaltedDigest", 0.008 ],
441             "MD5" => [ "Authen::Passphrase::SaltedDigest", 0.008 ],
442             "MSNT" => [ "Authen::Passphrase::NTHash", 0.003 ],
443             "NS-MTA-MD5" => [ "Authen::Passphrase::NetscapeMail", 0.003 ],
444             "RMD160" => [ "Authen::Passphrase::SaltedDigest", 0.008 ],
445             "SASL" => sub($) { croak "{SASL} is a placeholder" },
446             "SHA" => [ "Authen::Passphrase::SaltedDigest", 0.008 ],
447             "SMD5" => [ "Authen::Passphrase::SaltedDigest", 0.008 ],
448             "SSHA" => [ "Authen::Passphrase::SaltedDigest", 0.008 ],
449             "UNIX" => sub($) { croak "{UNIX} is a placeholder" },
450             # "WM-CRY" is handled specially
451             );
452              
453             sub from_rfc2307 {
454 11     11 1 3350 my($class, $userpassword) = @_;
455 11 50       113 if($userpassword =~ m#\A\{(?i:crypt|wm-cry)\}(.*)\z#s) {
456 11         35 my $passwd = $1;
457 11         59 return $class->from_crypt($passwd);
458             }
459 0 0       0 croak "RFC 2307 string \"$userpassword\" not supported for $class"
460             unless $class eq __PACKAGE__;
461 0 0       0 $userpassword =~ /\A\{([-0-9a-z]+)\}/i
462             or croak "bad RFC 2307 syntax in \"$userpassword\"";
463 0         0 my $scheme = uc($1);
464 0         0 my $handler = $rfc2307_scheme_handler{$scheme};
465 0 0       0 croak "unrecognised RFC 2307 scheme {$scheme}" unless defined $handler;
466 0 0       0 if(ref($handler) eq "CODE") {
467 0         0 return $handler->($userpassword);
468             } else {
469 0         0 my($modname, $modver) = @$handler;
470 0         0 return use_module($modname, $modver)
471             ->from_rfc2307($userpassword);
472             }
473             }
474              
475             =back
476              
477             =head1 METHODS
478              
479             =over
480              
481             =item $ppr->match(PASSPHRASE)
482              
483             Checks whether the supplied passphrase is correct. Returns a truth value.
484              
485             The passphrase is expected to be octets, not characters.
486              
487             =item $ppr->passphrase
488              
489             If a matching passphrase can be easily determined by the passphrase
490             recogniser then this method will return it. This is only feasible for
491             very weak passphrase schemes. The method Cs if it is infeasible.
492              
493             =item $ppr->as_crypt
494              
495             Encodes the passphrase recogniser in crypt format and returns the encoded
496             result. Cs if the passphrase recogniser cannot be represented in
497             this form.
498              
499             =item $ppr->as_rfc2307
500              
501             Encodes the passphrase recogniser in RFC 2307 format and returns
502             the encoded result. Cs if the passphrase recogniser cannot be
503             represented in this form.
504              
505             =cut
506              
507 73     73 1 6233 sub as_rfc2307 { "{CRYPT}".$_[0]->as_crypt }
508              
509             =back
510              
511             =head1 SUBCLASSING
512              
513             This class is designed to be subclassed, and cannot be instantiated alone.
514             Any subclass must implement the L method. That is the minimum
515             required.
516              
517             Subclasses should implement the L and L methods
518             and the L and L constructors wherever
519             appropriate, with the following exception. If a passphrase scheme has
520             a crypt encoding but no native RFC 2307 encoding, so it can be RFC 2307
521             encoded only by using the "B<{CRYPT}>" scheme, then L and
522             L should I be implemented by the class. There is a
523             default implementation of the L method that uses "B<{CRYPT}>"
524             and L, and a default implementation of the L
525             method that recognises "B<{CRYPT}>" and passes the embedded crypt string
526             to the L constructor.
527              
528             Implementation of the L method is entirely optional.
529             It should be attempted only for schemes that are so ludicrously weak as
530             to allow passphrases to be cracked reliably in a short time. Dictionary
531             attacks are not appropriate implementations.
532              
533             =head1 SEE ALSO
534              
535             L,
536             L,
537             RFC 2307
538              
539             =head1 AUTHOR
540              
541             Andrew Main (Zefram)
542              
543             =head1 COPYRIGHT
544              
545             Copyright (C) 2006, 2007, 2009, 2010, 2012
546             Andrew Main (Zefram)
547              
548             =head1 LICENSE
549              
550             This module is free software; you can redistribute it and/or modify it
551             under the same terms as Perl itself.
552              
553             =cut
554              
555             1;