From: scottmk Date: Mon, 28 Dec 2009 03:50:38 +0000 (+0000) Subject: Add routines for calculating SHA1 and MD5 digests, based on the X-Git-Tag: osrf_rel_2_0_1~211 X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=bfade5af82624b7928a50a69cf0434c4740cb986;p=OpenSRF.git Add routines for calculating SHA1 and MD5 digests, based on the gnutls package. These routines are designed to replace the current functions shahash() and md5sum(), but they are not drop-in replacements because they have different signatures. Prerequisites: packages gcrypt and gnutls. This code is based on a contribution by Jason Stephenson. A include/opensrf/osrf_digest.h A src/libopensrf/osrf_digest.c git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@1879 9efc2488-bf62-4759-914b-345cdb29e865 --- diff --git a/include/opensrf/osrf_digest.h b/include/opensrf/osrf_digest.h new file mode 100644 index 0000000..a3380fa --- /dev/null +++ b/include/opensrf/osrf_digest.h @@ -0,0 +1,63 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009 Equinox Software Inc. + */ + +/** + @file osrf_digest.h + @brief Header for digest functions. + + In each case, the input is a nul-terminated character string. The result is returned + in a structure provided by the calling code, both in a binary buffer and in a + nul-terminated string of hex characters encoding the same value. +*/ + +#ifndef OSRF_DIGEST_H +#define OSRF_DIGEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + @brief Contains an SHA1 digest. +*/ +typedef struct { + unsigned char binary[ 20 ]; /**< Binary SHA1 digest. */ + char hex[ 41 ]; /**< Same digest, in the form of a hex string. */ +} osrfSHA1Buffer; + +/** + @brief Contains an MD5 digest. +*/ +typedef struct { + unsigned char binary[ 16 ]; /**< Binary MD5 digest. */ + char hex[ 33 ]; /**< Same digest, in the form of a hex string. */ +} osrfMD5Buffer; + +void osrf_sha1_digest( osrfSHA1Buffer* result, const char *str ); + +void osrf_sha1_digest_fmt( osrfSHA1Buffer* result, const char* str, ... ); + +void osrf_md5_digest( osrfMD5Buffer* result, const char *str ); + +void osrf_md5_digest_fmt( osrfMD5Buffer* result, const char* str, ... ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/libopensrf/osrf_digest.c b/src/libopensrf/osrf_digest.c new file mode 100644 index 0000000..e56242c --- /dev/null +++ b/src/libopensrf/osrf_digest.c @@ -0,0 +1,135 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009 Jason J.A. Stephenson + * Extensively modified by Scott McKellar + * Copyright 2009 Equinox Software Inc. + */ + +/** + @file osrf_digest.c + @brief Routines to calculate SHA1 and MD5 digests of strings. +*/ + +#include +#include +#include +#include "opensrf/utils.h" +#include "opensrf/osrf_digest.h" + +static void format_hex( char* buf, const unsigned char* s, size_t n ); + +/** + @brief Calculate an SHA1 digest for a specified string. + @param result Pointer to an osrfSHA1Buffer to receive the result. + @param str Pointer to a nul-terminated string to be digested. +*/ +void osrf_sha1_digest( osrfSHA1Buffer* result, const char *str ) { + if( !result ) + return; + + result->hex[0] = '\0'; + + if( str ) { + size_t out_size = sizeof( result->binary ); /* SHA1 is 160 bits output. */ + + gnutls_datum_t in; + in.data = (unsigned char*) str; + in.size = strlen( str ); + if( gnutls_fingerprint( GNUTLS_DIG_SHA1, &in, result->binary, &out_size ) + == GNUTLS_E_SUCCESS ) { + format_hex( result->hex, result->binary, out_size ); + } + } +} + +/** + @brief Calculate an SHA1 digest for a formatted string. + @param result Pointer to an osrfSHA1Buffer to receive the result. + @param str Pointer to a printf-style format string. Subsequent arguments, if any, are + formatted and inserted into the string to be digested. +*/ +void osrf_sha1_digest_fmt( osrfSHA1Buffer* result, const char* str, ... ) { + if( str ) { + VA_LIST_TO_STRING( str ); + osrf_sha1_digest( result, VA_BUF ); + } else if( result ) + result->hex[0] = '\0'; +} + +/** + @brief Calculate an MD5 digest for a specified string. + @param result Pointer to an osrfMD5Buffer to receive the result. + @param str Pointer to a nul-terminated string to be digested. +*/ +void osrf_md5_digest( osrfMD5Buffer* result, const char *str ) { + if( !result ) + return; + + result->hex[0] = '\0'; + + if( str ) { + size_t out_size = sizeof( result->binary ); /* MD5 is 128 bits output. */ + + gnutls_datum_t in; + in.data = (unsigned char*) str; + in.size = strlen( str ); + if( gnutls_fingerprint( GNUTLS_DIG_MD5, &in, result->binary, &out_size ) + == GNUTLS_E_SUCCESS ) { + format_hex( result->hex, result->binary, out_size ); + } + } +} + +/** + @brief Calculate an MD5 digest for a formatted string. + @param result Pointer to an osrfMD5Buffer to receive the result. + @param str Pointer to a printf-style format string. Subsequent arguments, if any, are + formatted and inserted into the string to be digested. +*/ +void osrf_md5_digest_fmt( osrfMD5Buffer* result, const char* str, ... ) { + if( str ) { + VA_LIST_TO_STRING( str ); + osrf_md5_digest( result, VA_BUF ); + } else if( result ) + result->hex[0] = '\0'; +} + +/** + @brief Translate a series of bytes to the corresponding hexadecimal representation. + @param buf Pointer to the buffer that will receive the output hex characters. + @param s Pointer to the input characters to be translated. + @param n How many input characters to translate. + + The calling code is responsible for providing a large enough output buffer. It should + be twice as large as the buffer to be translated, plus one for a terminal nul. +*/ +static void format_hex( char* buf, const unsigned char* s, size_t n ) { + int i; + for( i = 0; i < n; ++i ) { + unsigned char c = s[i]; + + // Format high nybble + unsigned char fc = ( c >> 4 ) & 0x0F; + fc += (fc > 9) ? 'a' - 10 : '0'; + *buf++ = fc; + + // Format low nybble + fc = c & 0x0F; + fc += (fc > 9) ? 'a' - 10 : '0'; + *buf++ = fc; + } + *buf = '\0'; +}