MFH (r261913): switch default to sha512

MFH (r264964): rewrite so DES still works when not the default
MFH (r262945): clean up man page
This commit is contained in:
Dag-Erling Smørgrav 2014-05-11 14:54:17 +00:00
parent 3e35f5c89f
commit 895309a5b5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/stable/10/; revision=265879
2 changed files with 93 additions and 110 deletions

View File

@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd April 9, 2011
.Dd March 9, 2014
.Dt CRYPT 3
.Os
.Sh NAME
@ -63,11 +63,16 @@ Currently these include the
.Tn MD5
hash,
.Tn NT-Hash
(compatible with Microsoft's NT scheme)
.Pq compatible with Microsoft's NT scheme
and
.Tn Blowfish .
The algorithm used will depend upon the format of the Salt (following
the Modular Crypt Format (MCF)), if
The algorithm used will depend upon the format of the Salt
.Po
following
the Modular Crypt Format
.Pq MCF
.Pc ,
if
.Tn DES
and/or
.Tn Blowfish
@ -77,8 +82,10 @@ has been called to change the default.
.Pp
The first argument to
.Nm
is the data to hash (usually a password), in a
.Dv null Ns -terminated
is the data to hash
.Pq usually a password ,
in a
.Dv NUL Ns -terminated
string.
The second is the salt, in one of three forms:
.Pp
@ -96,22 +103,19 @@ If it begins with the string
then the Modular Crypt Format is used, as outlined below.
.It Traditional
If neither of the above is true, it assumes the Traditional Format,
using the entire string as the salt (or the first portion).
using the entire string as the salt
.Pq or the first portion .
.El
.Pp
All routines are designed to be time-consuming.
A brief test on a
.Tn Pentium
166/MMX shows the
.Tn DES
crypt to do approximately 2640 crypts
a CPU second and MD5 to do about 62 crypts a CPU second.
.Ss DES Extended Format:
The
.Ar key
is divided into groups of 8 characters (the last group is null-padded)
and the low-order 7 bits of each character (56 bits per group) are
used to form the
is divided into groups of 8 characters
.Pq the last group is NUL-padded
and the low-order 7 bits of each character
.Pq 56 bits per group
are used to form the
.Tn DES
key as follows:
the first group of 56 bits becomes the initial
@ -127,7 +131,8 @@ The salt is a 9-character array consisting of an underscore followed
by 4 bytes of iteration count and 4 bytes of salt.
These are encoded as printable characters, 6 bits per character,
least significant character first.
The values 0 to 63 are encoded as ``./0-9A-Za-z''.
The values 0 to 63 are encoded as
.Dq ./0-9A-Za-z .
This allows 24 bits for both
.Fa count
and
@ -138,7 +143,8 @@ The
introduces disorder in the
.Tn DES
algorithm in one of 16777216 or 4096 possible ways
(i.e., with 24 or 12 bits: if bit
.Po
i.e., with 24 or 12 bits: if bit
.Em i
of the
.Ar salt
@ -148,7 +154,8 @@ and
.Em i+24
are swapped in the
.Tn DES
E-box output).
E-box output
.Pc .
.Pp
The
.Tn DES
@ -157,11 +164,13 @@ key is used to encrypt a 64-bit constant using
iterations of
.Tn DES .
The value returned is a
.Dv null Ns -terminated
string, 20 or 13 bytes (plus null) in length, consisting of the
.Dv NUL Ns -terminated
string, 20 or 13 bytes
.Pq plus NUL
in length, consisting of the
.Ar salt
followed by the encoded 64-bit encryption.
.Ss "Modular" crypt:
.Ss Modular crypt:
If the salt begins with the string
.Fa $digit$
then the Modular Crypt Format is used.
@ -170,11 +179,10 @@ The
represents which algorithm is used in encryption.
Following the token is
the actual salt to use in the encryption.
The length of the salt is limited
to 8 characters--because the length of the returned output is also limited
(_PASSWORD_LEN).
The salt must be terminated with the end of the string
(NULL) or a dollar sign.
The maximum length of the salt used depends upon the module.
The salt must be terminated with the end of the string character
.Pq NUL
or a dollar sign.
Any characters after the dollar sign are ignored.
.Pp
Currently supported algorithms are:
@ -199,7 +207,7 @@ An example salt would be:
.Bl -tag -width 6n -offset indent
.It Cm "$4$thesalt$rest"
.El
.Ss "Traditional" crypt:
.Ss Traditional crypt:
The algorithm used will depend upon whether
.Fn crypt_set_format
has been called and whether a global default format has been specified.
@ -216,7 +224,7 @@ if it is available, or MD5 if not.
.Pp
How the salt is used will depend upon the algorithm for the hash.
For
best results, specify at least two characters of salt.
best results, specify at least eight characters of salt.
.Pp
The
.Fn crypt_get_format

View File

@ -1,6 +1,7 @@
/*
* Copyright (c) 1999
* Mark Murray. All rights reserved.
/*-
* Copyright (c) 1999 Mark Murray
* Copyright (c) 2014 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -28,114 +29,88 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <string.h>
#include <libutil.h>
#include <string.h>
#include <unistd.h>
#include "crypt.h"
static const struct {
/*
* List of supported crypt(3) formats. The first element in the list will
* be the default.
*/
static const struct crypt_format {
const char *const name;
char *(*const func)(const char *, const char *);
const char *const magic;
} crypt_types[] = {
#ifdef HAS_DES
{
"des",
crypt_des,
NULL
},
#endif
{
"md5",
crypt_md5,
"$1$"
},
} crypt_formats[] = {
/* default format */
{ "sha512", crypt_sha512, "$6$" },
/* other supported formats */
{ "md5", crypt_md5, "$1$" },
#ifdef HAS_BLOWFISH
{
"blf",
crypt_blowfish,
"$2"
},
{ "blf", crypt_blowfish, "$2" },
#endif
{
"nth",
crypt_nthash,
"$3$"
},
{
"sha256",
crypt_sha256,
"$5$"
},
{
"sha512",
crypt_sha512,
"$6$"
},
{
NULL,
NULL,
NULL
}
{ "nth", crypt_nthash, "$3$" },
{ "sha256", crypt_sha256, "$5$" },
#ifdef HAS_DES
{ "des", crypt_des, "_" },
#endif
/* sentinel */
{ NULL, NULL, NULL }
};
#ifdef HAS_DES
#define CRYPT_DEFAULT "des"
#else
#define CRYPT_DEFAULT "md5"
#endif
static const struct crypt_format *crypt_format = &crypt_formats[0];
static int crypt_type = -1;
static void
crypt_setdefault(void)
{
size_t i;
if (crypt_type != -1)
return;
for (i = 0; i < sizeof(crypt_types) / sizeof(crypt_types[0]) - 1; i++) {
if (strcmp(CRYPT_DEFAULT, crypt_types[i].name) == 0) {
crypt_type = (int)i;
return;
}
}
crypt_type = 0;
}
#define DES_SALT_ALPHABET \
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
/*
* Returns the name of the currently selected format.
*/
const char *
crypt_get_format(void)
{
crypt_setdefault();
return (crypt_types[crypt_type].name);
return (crypt_format->name);
}
/*
* Selects the format to use for subsequent crypt(3) invocations.
*/
int
crypt_set_format(const char *type)
crypt_set_format(const char *format)
{
size_t i;
const struct crypt_format *cf;
crypt_setdefault();
for (i = 0; i < sizeof(crypt_types) / sizeof(crypt_types[0]) - 1; i++) {
if (strcmp(type, crypt_types[i].name) == 0) {
crypt_type = (int)i;
for (cf = crypt_formats; cf->name != NULL; ++cf) {
if (strcasecmp(cf->name, format) == 0) {
crypt_format = cf;
return (1);
}
}
return (0);
}
/*
* Hash the given password with the given salt. If the salt begins with a
* magic string (e.g. "$6$" for sha512), the corresponding format is used;
* otherwise, the currently selected format is used.
*/
char *
crypt(const char *passwd, const char *salt)
{
size_t i;
const struct crypt_format *cf;
crypt_setdefault();
for (i = 0; i < sizeof(crypt_types) / sizeof(crypt_types[0]) - 1; i++) {
if (crypt_types[i].magic != NULL && strncmp(salt,
crypt_types[i].magic, strlen(crypt_types[i].magic)) == 0)
return (crypt_types[i].func(passwd, salt));
}
return (crypt_types[crypt_type].func(passwd, salt));
for (cf = crypt_formats; cf->name != NULL; ++cf)
if (cf->magic != NULL && strstr(salt, cf->magic) == salt)
return (cf->func(passwd, salt));
#ifdef HAS_DES
if (strlen(salt) == 13 && strspn(salt, DES_SALT_ALPHABET) == 13)
return (crypt_des(passwd, salt));
#endif
return (crypt_format->func(passwd, salt));
}