Created
September 25, 2013 11:07
-
-
Save stbuehler/6698128 to your computer and use it in GitHub Desktop.
create crypt() hashes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Build: | |
* LDFLAGS=-lcrypt make mkcrypt | |
* | |
* Usage: | |
* mkcrypt [algo [saltlen [randomsource]]] | |
* | |
* - reads password from stdin (tries to set echo off) | |
* | |
* Defaults to $6$ as algo, 16 for saltlen and /dev/random for the | |
* random source. | |
* | |
* For password verification use: mkcrypt '$6$andsomesalt$' 0 | |
* - that is, specify algo+salt as algo, and 0 as saltlen. | |
* | |
* If saltlen is 0 the randomsource isn't used. | |
* | |
* Uses the standard crypt() function, no special algos supported. | |
*/ | |
#define _XOPEN_SOURCE 500 | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <termio.h> | |
#include <unistd.h> | |
static const char *randomdev = "/dev/random"; | |
static const unsigned char saltchars[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | |
int create_salt(unsigned char *buf, int len) { | |
if (0 == len) return 1; | |
int c, i; | |
FILE *rnd = fopen(randomdev, "rb"); | |
if (NULL == rnd) return 0; | |
for (i = 0; i < len && EOF != (c = fgetc(rnd)); ++i, ++buf) { | |
unsigned char b = (unsigned char) c; | |
*buf = saltchars[b % 64]; | |
} | |
fclose(rnd); | |
return 1; | |
} | |
char *create_password_hash(const char *algo, unsigned int saltlen, const char *password) { | |
unsigned int algolen = strlen(algo); | |
/* algo may contains parameters like rounds=... */ | |
if (algolen > 30 || saltlen > 16) return NULL; | |
unsigned int buflen = algolen + saltlen + 1; | |
unsigned char buf[buflen]; | |
memset(buf, 0, buflen); | |
memcpy(buf, algo, algolen); | |
if (!create_salt(buf + algolen, saltlen)) return NULL; | |
/* fprintf(stderr, "crypt: '%s'\n", buf); */ | |
char *hash = crypt(password, buf); | |
if (0 != strncmp(hash, buf, algolen + saltlen)) return NULL; | |
return hash; | |
} | |
void echo_off(struct termio *save) { | |
struct termio t; | |
if (ioctl(0, TCGETA, &t) == -1) return; | |
if (NULL != save) *save = t; | |
t.c_lflag &= ~(ICANON|ECHO); | |
t.c_cc[VMIN] = 1; | |
t.c_cc[VTIME] = 0; | |
ioctl(0, TCSETA, &t); | |
} | |
void restore(struct termio *save) { | |
ioctl(0, TCSETA, save); | |
} | |
int main(int argc, char **argv) { | |
char password[1024]; | |
struct termio tsave; | |
int saltlen = 16; | |
const char *algo = "$6$"; | |
char *hash; | |
int pwlen; | |
if (argc > 1) { | |
if (0 == strcmp("-h", argv[1]) || 0 == strcmp("-?", argv[1]) || 0 == strcmp("--help", argv[1])) { | |
fputs("Syntax: mkcrypt [algo [saltlen [randomsource]]]\n", stderr); | |
exit(2); | |
} | |
char *algosalt = strdup(argv[1]); | |
algo = algosalt; | |
/* cut off the part after the salt */ | |
if (algosalt[0] == '$' && algosalt[1] != 0 && algosalt[2] == '$') { | |
algosalt = strchr(algosalt+3, '$'); | |
if (NULL != algosalt) { | |
*algosalt = 0; | |
saltlen = 0; | |
} | |
} else if (algosalt[0] != 0 && algosalt[1] != 0) { | |
algosalt[2] = 0; | |
saltlen = 0; | |
} | |
if (argc > 2) { | |
saltlen = atoi(argv[2]); | |
} | |
if (argc > 3) { | |
randomdev = argv[3]; | |
} | |
} | |
/* fprintf(stderr, "Algo: '%s', saltlen: %i\n", algo, saltlen); */ | |
echo_off(&tsave); | |
fputs("Enter password: ", stdout); | |
if (NULL == fgets(password, 1024, stdin)) { | |
restore(&tsave); | |
fputc('\n', stdout); | |
exit(1); | |
} | |
restore(&tsave); | |
fputc('\n', stdout); | |
pwlen = strlen(password); | |
while (pwlen > 0 && password[pwlen-1] < 32) { | |
--pwlen; | |
password[pwlen] = 0; | |
} | |
hash = create_password_hash(algo, saltlen, password); | |
memset(password, 0, sizeof(password)); | |
if (NULL == hash) { | |
fputs("Failed to generate hash\n", stderr); | |
exit(1); | |
} | |
fputs(hash, stdout); | |
fputc('\n', stdout); | |
memset(hash, 0, strlen(hash)); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment