From 792b6373efffdd3ebfb8dd9a02fcdeff9c742024 Mon Sep 17 00:00:00 2001 From: Andreas Lange <andreas@lange.cx> Date: Mon, 30 Apr 2001 02:33:42 +0200 Subject: [PATCH] Added crypt_md5() Rev: src/modules/_Crypto/crypto.c:1.45 Rev: src/modules/_Crypto/crypto.h:1.7 Rev: src/modules/_Crypto/lib/Makefile.in:1.29 Rev: src/modules/_Crypto/lib/crypt_md5.c:1.1 Rev: src/modules/_Crypto/testsuite.in:1.17 --- .gitattributes | 1 + src/modules/_Crypto/crypto.c | 54 +++++++++- src/modules/_Crypto/crypto.h | 4 +- src/modules/_Crypto/lib/Makefile.in | 4 +- src/modules/_Crypto/lib/crypt_md5.c | 152 ++++++++++++++++++++++++++++ src/modules/_Crypto/testsuite.in | 6 ++ 6 files changed, 216 insertions(+), 5 deletions(-) create mode 100644 src/modules/_Crypto/lib/crypt_md5.c diff --git a/.gitattributes b/.gitattributes index e2ffa3bff3..9224117406 100644 --- a/.gitattributes +++ b/.gitattributes @@ -461,6 +461,7 @@ testfont binary /src/modules/_Crypto/lib/cast.c foreign_ident /src/modules/_Crypto/lib/cast_sboxes.h foreign_ident /src/modules/_Crypto/lib/configure.in foreign_ident +/src/modules/_Crypto/lib/crypt_md5.c foreign_ident /src/modules/_Crypto/lib/desCode.h foreign_ident /src/modules/_Crypto/lib/desKerb.c foreign_ident /src/modules/_Crypto/lib/desQuick.c foreign_ident diff --git a/src/modules/_Crypto/crypto.c b/src/modules/_Crypto/crypto.c index afcc059885..eea6712b53 100644 --- a/src/modules/_Crypto/crypto.c +++ b/src/modules/_Crypto/crypto.c @@ -1,5 +1,5 @@ /* - * $Id: crypto.c,v 1.44 2001/03/28 15:07:41 grubba Exp $ + * $Id: crypto.c,v 1.45 2001/04/30 00:33:41 lange Exp $ * * A pike module for getting access to some common cryptos. * @@ -246,6 +246,55 @@ static void f_des_parity(INT32 args) push_string(end_shared_string(s)); } +/*! @decl string crypt_md5(string password) + *! @decl string crypt_md5(string password, string salt) + *! + *! This function crypts a password with an algorithm using MD5 hashing. + *! + *! If @[salt] is left out, an 8 character long salt (max length) will + *! be randomized. + *! + *! Verification can be done by supplying the crypted password as @[salt]: + *! @code{crypt_md5(typed_pw, crypted_pw) == crypted_pw} + *! + *! @seealso + *! @[crypt()] + */ +static void f_crypt_md5(INT32 args) +{ + char salt[8]; + char *ret, *saltp =""; + char *choice = + "cbhisjKlm4k65p7qrJfLMNQOPxwzyAaBDFgnoWXYCZ0123tvdHueEGISRTUV89./"; + + if (args < 1) + SIMPLE_TOO_FEW_ARGS_ERROR("crypt_md5", 1); + + if (Pike_sp[-args].type != T_STRING) + SIMPLE_BAD_ARG_ERROR("crypt_md5", 1, "string"); + + if (args > 1) + { + if (Pike_sp[1-args].type != T_STRING) + SIMPLE_BAD_ARG_ERROR("crypt_md5", 2, "string"); + + saltp = Pike_sp[1-args].u.string->str; + } else { + unsigned int i, r; + for (i = 0; i < sizeof(salt); i++) + { + r = my_rand(); + salt[i] = choice[r % (size_t) strlen(choice)]; + } + saltp = salt; + } + + ret = (char *)crypt_md5(Pike_sp[-args].u.string->str, saltp); + + pop_n_elems(args); + push_string(make_shared_string(ret)); +} + /* * Crypto */ @@ -585,6 +634,9 @@ void pike_module_init(void) ADD_FUNCTION("hex_to_string", f_hex_to_string, tFunc(tStr, tStr), 0); /* function(string:string) */ ADD_FUNCTION("des_parity", f_des_parity, tFunc(tStr, tStr), 0); + /* function(string:string)|function(string,string:string) */ + ADD_FUNCTION("crypt_md5", f_crypt_md5, + tOr(tFunc(tStr,tStr), tFunc(tStr tStr,tStr)), 0); pike_md2_init(); pike_md5_init(); diff --git a/src/modules/_Crypto/crypto.h b/src/modules/_Crypto/crypto.h index 497a669471..2fa621b802 100644 --- a/src/modules/_Crypto/crypto.h +++ b/src/modules/_Crypto/crypto.h @@ -1,5 +1,5 @@ /* - * $Id: crypto.h,v 1.6 2000/10/02 19:35:02 grubba Exp $ + * $Id: crypto.h,v 1.7 2001/04/30 00:33:41 lange Exp $ * * Prototypes for some functions. * @@ -34,4 +34,4 @@ extern void pike_rsa_init(void); extern void pike_rsa_exit(void); extern void pike_pipe_init(void); extern void pike_pipe_exit(void); - +extern char *crypt_md5(const char *pw, const char *salt); diff --git a/src/modules/_Crypto/lib/Makefile.in b/src/modules/_Crypto/lib/Makefile.in index 47702d61f6..8f8b7c503b 100644 --- a/src/modules/_Crypto/lib/Makefile.in +++ b/src/modules/_Crypto/lib/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.28 2001/01/19 20:24:12 grubba Exp $ +# $Id: Makefile.in,v 1.29 2001/04/30 00:33:41 lange Exp $ # # Makefile for low-level crypto library @@ -160,7 +160,7 @@ desQuickCore.c: MASS_DESTRUCTION_OBJS = idea.o arcfour.o cast.o rijndael.o $(O) # END NATIONAL SECURITY -OBJS = $(MASS_DESTRUCTION_OBJS) sha.o md2.o md5.o +OBJS = $(MASS_DESTRUCTION_OBJS) sha.o md2.o md5.o crypt_md5.o rijndael.o: $(SRCDIR)/../include/rijndael.h rijndael-boxes.dat diff --git a/src/modules/_Crypto/lib/crypt_md5.c b/src/modules/_Crypto/lib/crypt_md5.c new file mode 100644 index 0000000000..d9ae7cd052 --- /dev/null +++ b/src/modules/_Crypto/lib/crypt_md5.c @@ -0,0 +1,152 @@ +/* + * $Id: crypt_md5.c,v 1.1 2001/04/30 00:33:42 lange Exp $ + * + * crypt-md5.c : Implementation of the MD5 password hash function + * + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + * Adapted to Pike by Andreas Lange + * + */ + +#include <string.h> +#include "crypto_types.h" +#include "md5.h" + + +static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static void to64(char *s, unsigned long v, int n) +{ + while (--n >= 0) { + *s++ = itoa64[v & 0x3f]; + v >>= 6; + } +} + + +char *crypt_md5(const char *pw, const char *salt) +{ + static char *magic = "$1$"; /* + * This string is magic for + * this algorithm. Having + * it this way, we can get + * better later on + */ + static char passwd[120], *p; + static const char *sp, *ep; + unsigned char final[MD5_DIGESTSIZE]; + int sl, pl, i; + struct md5_ctx ctx, ctx1; + unsigned long l; + + /* Refine the Salt first */ + sp = salt; + + /* If it starts with the magic string, then skip that */ + if (!strncmp(sp, magic, strlen(magic))) + sp += strlen(magic); + + /* It stops at the first '$', max 8 chars */ + for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++) + continue; + + /* get the length of the true salt */ + sl = ep - sp; + + md5_init(&ctx); + + /* The password first, since that is what is most unknown */ + md5_update(&ctx, (unsigned INT8 *) pw, strlen(pw)); + + /* Then our magic string */ + md5_update(&ctx, (unsigned INT8 *) magic, strlen(magic)); + + /* Then the raw salt */ + md5_update(&ctx, (unsigned INT8 *) sp, sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + md5_init(&ctx1); + md5_update(&ctx1, (unsigned INT8 *) pw, strlen(pw)); + md5_update(&ctx1, (unsigned INT8 *) sp, sl); + md5_update(&ctx1, (unsigned INT8 *) pw, strlen(pw)); + md5_final(&ctx1); + md5_digest(&ctx1, final); + for(pl = strlen(pw); pl > 0; pl -= MD5_DIGESTSIZE) + md5_update(&ctx, (unsigned INT8 *) final, + pl>MD5_DIGESTSIZE ? MD5_DIGESTSIZE : pl); + + /* Don't leave anything around in vm they could use. */ + memset(final, 0, sizeof(final) ); + + /* Then something really weird... */ + for (i = strlen(pw); i ; i >>= 1) + if(i&1) + md5_update(&ctx, (unsigned INT8 *) final, 1); + else + md5_update(&ctx, (unsigned INT8 *) pw, 1); + + /* Now make the output string */ + strcpy(passwd, magic); + strncat(passwd, sp, sl); + strcat(passwd, "$"); + + md5_final(&ctx); + md5_digest(&ctx, final); + + /* And now, just to make sure things don't run too fast... */ + for(i=0;i<1000;i++) { + md5_init(&ctx1); + if(i & 1) + md5_update(&ctx1, (unsigned INT8 *) pw, strlen(pw)); + else + md5_update(&ctx1, (unsigned INT8 *) final, MD5_DIGESTSIZE); + + if(i % 3) + md5_update(&ctx1, (unsigned INT8 *) sp, sl); + + if(i % 7) + md5_update(&ctx1, (unsigned INT8 *) pw, strlen(pw)); + + if(i & 1) + md5_update(&ctx1, (unsigned INT8 *) final, MD5_DIGESTSIZE); + else + md5_update(&ctx1, (unsigned INT8 *) pw, strlen(pw)); + + md5_final(&ctx1); + md5_digest(&ctx1, final); + } + + p = passwd + strlen(passwd); + + l = (final[0] << 16) | (final[6] << 8) | final[12]; + to64(p, l, 4); + p += 4; + l = (final[1] << 16) | (final[7] << 8) | final[13]; + to64(p, l, 4); + p += 4; + l = (final[2] << 16) | (final[8] << 8) | final[14]; + to64(p, l, 4); + p += 4; + l = (final[3] << 16) | (final[9] << 8) | final[15]; + to64(p, l, 4); + p += 4; + l = (final[4] << 16) | (final[10] << 8) | final[5]; + to64(p, l, 4); + p += 4; + l = final[11]; + to64(p, l, 2); + p += 2; + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final, 0, sizeof(final) ); + + return passwd; +} diff --git a/src/modules/_Crypto/testsuite.in b/src/modules/_Crypto/testsuite.in index 2d57660128..e4efeb9836 100644 --- a/src/modules/_Crypto/testsuite.in +++ b/src/modules/_Crypto/testsuite.in @@ -251,3 +251,9 @@ test_eq([[Crypto.hmac(xCrypto.sha)("Jefe")("what do ya want for nothing?")]], [[xCrypto.hex_to_string("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79")]]) test_eq([[Crypto.hmac(xCrypto.sha)("\252" * 16)("\335" * 50)]], [[xCrypto.hex_to_string("d730594d167e35d5956fd8003d0db3d3f46dc7bb")]]) + +// CRYPT_MD5 +test_eq([[xCrypto.crypt_md5("Hello","sl5hO7j4")]], + [["$1$sl5hO7j4$glLmY.ttmi1hWK8ucIrig."]]) +test_eq([[xCrypto.crypt_md5("Hello","$1$sl5hO7j4$glLmY.ttmi1hWK8ucIrig.")]], + [["$1$sl5hO7j4$glLmY.ttmi1hWK8ucIrig."]]) -- GitLab