<HTML> <HEAD> <TITLE>mhash library</TITLE> <LINK REV="made" HREF="mailto:perl@packages.debian.org"> </HEAD> <BODY> <A NAME="__index__"></A> <!-- INDEX BEGIN --> <!-- <UL> <LI><A HREF="#name"> <FONT SIZE=-1>NAME</FONT></A></LI> <LI><A HREF="#version"> <FONT SIZE=-1>VERSION</FONT></A></LI> <LI><A HREF="#synopsis"> <FONT SIZE=-1>SYNOPSIS</FONT></A></LI> <LI><A HREF="#description"> <FONT SIZE=-1>DESCRIPTION</FONT></A></LI> <LI><A HREF="#api functions"> <FONT SIZE=-1>API</FONT> <FONT SIZE=-1>FUNCTIONS</FONT></A></LI> <LI><A HREF="#keygen api functions"> <FONT SIZE=-1>KEYGEN</FONT> <FONT SIZE=-1>API</FONT> <FONT SIZE=-1>FUNCTIONS</FONT></A></LI> <LI><A HREF="#example"> <FONT SIZE=-1>EXAMPLE</FONT></A></LI> <LI><A HREF="#example"> <FONT SIZE=-1>EXAMPLE</FONT></A></LI> <LI><A HREF="#history"> <FONT SIZE=-1>HISTORY</FONT></A></LI> <LI><A HREF="#bugs"> <FONT SIZE=-1>BUGS</FONT></A></LI> <LI><A HREF="#authors"> <FONT SIZE=-1>AUTHORS</FONT></A></LI> </UL> --> <!-- INDEX END --> <P> <HR> <H1><A NAME="name"> <FONT SIZE=-1>NAME</FONT></A></H1> <P><STRONG>mhash - Hash Library</STRONG></P> <P> <HR> <H1><A NAME="version"> <FONT SIZE=-1>VERSION</FONT></A></H1> <P>mhash <FONT SIZE=-1>0.8.12</FONT></P> <P> <HR> <H1><A NAME="synopsis"> <FONT SIZE=-1>SYNOPSIS</FONT></A></H1> <PRE> #include "mhash.h"</PRE> <P><STRONG> Informative Functions </STRONG></P> <PRE> size_t mhash_count(void); size_t mhash_get_block_size(hashid type); char *mhash_get_hash_name(hashid type); size_t mhash_get_hash_pblock(hashid type); hashid mhash_get_mhash_algo( MHASH);</PRE> <P><STRONG> Key Generation Functions </STRONG></P> <PRE> int mhash_keygen_ext(keygenid algorithm, KEYGEN algorithm_data, void* keyword, int keysize, unsigned char* password, int passwordlen);</PRE> <P><STRONG> Initializing Functions </STRONG></P> <PRE> MHASH mhash_init(hashid type); MHASH mhash_hmac_init(const hashid type, void *key, int keysize, int block); MHASH mhash_cp( MHASH);</PRE> <P><STRONG> Update Functions </STRONG></P> <PRE> int mhash(MHASH thread, const void *plaintext, size_t size);</PRE> <P><STRONG> Save/Restore Functions </STRONG></P> <PRE> int mhash_save_state_mem(MHASH thread, void *mem, int* mem_size ); MHASH mhash_restore_state_mem(void* mem);</PRE> <P><STRONG> Finalizing Functions </STRONG></P> <PRE> void mhash_deinit(MHASH thread, void *result); void *mhash_end(MHASH thread); void *mhash_end_m(MHASH thread, void* (*hash_malloc)(size_t));</PRE> <PRE> void *mhash_hmac_end(MHASH thread); void *mhash_hmac_end_m(MHASH thread, void* (*hash_malloc)(size_t)); int mhash_hmac_deinit(MHASH thread, void *result);</PRE> <P><STRONG> Available Hashes </STRONG></P> <P><EM> <FONT SIZE=-1>CRC32</FONT></EM>: The crc32 algorithm used to compute checksums. The two variants used in mhash are: <STRONG> <FONT SIZE=-1>MHASH_CRC32</FONT></STRONG> (like the one used in ethernet) and <STRONG> <FONT SIZE=-1>MHASH_CRC32B</FONT></STRONG> (like the one used in <FONT SIZE=-1>ZIP</FONT> programs).</P> <P><EM> <FONT SIZE=-1>MD5</FONT></EM>: The <FONT SIZE=-1>MD5</FONT> algorithm by Ron Rivest and <FONT SIZE=-1>RSA.</FONT> In mhash this algorithm is defined as <STRONG> <FONT SIZE=-1>MHASH_MD5</FONT></STRONG>.</P> <P><EM> <FONT SIZE=-1>MD4</FONT></EM>: The <FONT SIZE=-1>MD4</FONT> algorithm by Ron Rivest and <FONT SIZE=-1>RSA.</FONT> This algorithm is considered broken, so don't use it. In mhash this algorithm is defined as <STRONG> <FONT SIZE=-1>MHASH_MD4</FONT></STRONG>.</P> <P><EM> <FONT SIZE=-1>SHA1</FONT></EM>/<EM> <FONT SIZE=-1>SHA256</FONT></EM>: The <FONT SIZE=-1>SHA</FONT> algorithm by <FONT SIZE=-1>US.</FONT> <FONT SIZE=-1>NIST/NSA.</FONT> This algorithm is specified for use in the NIST's Digital Signature Standard. In mhash these algorithm are defined as <STRONG> <FONT SIZE=-1>MHASH_SHA1</FONT></STRONG> and <STRONG> <FONT SIZE=-1>MHASH_SHA256</FONT></STRONG>.</P> <P><EM> <FONT SIZE=-1>HAVAL</FONT></EM>: <FONT SIZE=-1>HAVAL</FONT> is a one-way hashing algorithm with variable length of output. <FONT SIZE=-1>HAVAL</FONT> is a modification of <FONT SIZE=-1>MD5.</FONT> Defined in mhash as: <STRONG> <FONT SIZE=-1>MHASH_HAVAL256,</FONT> <FONT SIZE=-1>MHASH_HAVAL192,</FONT> <FONT SIZE=-1>MHASH_HAVAL160,</FONT> <FONT SIZE=-1>MHASH_HAVAL128</FONT></STRONG>.</P> <P><EM> <FONT SIZE=-1>RIPEMD160</FONT></EM>: <FONT SIZE=-1>RIPEMD-160</FONT> is a 160-bit cryptographic hash function, designed by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel. It is intended to be used as a secure replacement for the 128-bit hash functions <FONT SIZE=-1>MD4,</FONT> <FONT SIZE=-1>MD5,</FONT> and <FONT SIZE=-1>RIPEMD.</FONT> <FONT SIZE=-1>MD4</FONT> and <FONT SIZE=-1>MD5</FONT> were developed by Ron Rivest for <FONT SIZE=-1>RSA</FONT> Data Security, while <FONT SIZE=-1>RIPEMD</FONT> was developed in the framework of the <FONT SIZE=-1>EU</FONT> project <FONT SIZE=-1>RIPE</FONT> <FONT SIZE=-1>(RACE</FONT> Integrity Primitives Evaluation, 1988-1992). In mhash this algorithm is defined as <STRONG> <FONT SIZE=-1>MHASH_RIPEMD160</FONT></STRONG>.</P> <P><EM> <FONT SIZE=-1>TIGER</FONT></EM>: Tiger is a fast hash function, by Eli Biham and Ross Anderson. Tiger was designed to be very fast on modern computers, and in particular on the state-of-the-art 64-bit computers, while it is still not slower than other suggested hash functions on 32-bit machines. In mhash this algorithm is defined as: <STRONG> <FONT SIZE=-1>MHASH_TIGER,</FONT> <FONT SIZE=-1>MHASH_TIGER160,</FONT> <FONT SIZE=-1>MHASH_TIGER128</FONT></STRONG>.</P> <P><EM> <FONT SIZE=-1>GOST</FONT></EM>: <FONT SIZE=-1>GOST</FONT> algorithm is a russian standard and it uses the <FONT SIZE=-1>GOST</FONT> encryption algorithm to produce a 256 bit hash value. This algorithm is specified for use in the Russian Digital Signature Standard. In mhash this algorithm is defined as <STRONG> <FONT SIZE=-1>MHASH_GOST</FONT></STRONG>.</P> <P><STRONG> Available Key Generation algorithms </STRONG></P> <P><EM> <FONT SIZE=-1>KEYGEN_MCRYPT</FONT></EM>: The key generator used in mcrypt.</P> <P><EM> <FONT SIZE=-1>KEYGEN_ASIS</FONT></EM>: Just returns the password as binary key.</P> <P><EM> <FONT SIZE=-1>KEYGEN_HEX</FONT></EM>: Just converts a hex key into a binary one.</P> <P><EM> <FONT SIZE=-1>KEYGEN_PKDES</FONT></EM>: The transformation used in Phil Karn's <FONT SIZE=-1>DES</FONT> encryption program.</P> <P><EM> <FONT SIZE=-1>KEYGEN_S2K_SIMPLE</FONT></EM>: The OpenPGP (rfc2440) Simple <FONT SIZE=-1>S2K.</FONT></P> <P><EM> <FONT SIZE=-1>KEYGEN_S2K_SALTED</FONT></EM>: The OpenPGP Salted <FONT SIZE=-1>S2K.</FONT></P> <P><EM> <FONT SIZE=-1>KEYGEN_S2K_ISALTED</FONT></EM>: The OpenPGP Iterated Salted <FONT SIZE=-1>S2K.</FONT></P> <P> <HR> <H1><A NAME="description"> <FONT SIZE=-1>DESCRIPTION</FONT></A></H1> <P>The <STRONG>mhash</STRONG> library provides an easy to use <FONT SIZE=-1>C</FONT> interface for several <EM>hash algorithms</EM> (also known as ``one-way'' algorithms). These can be used to create checksums, message digests and more. Currently, <FONT SIZE=-1>MD5,</FONT> <FONT SIZE=-1>SHA1,</FONT> <FONT SIZE=-1>GOST,</FONT> <FONT SIZE=-1>TIGER,</FONT> <FONT SIZE=-1>RIPE-MD160,</FONT> <FONT SIZE=-1>HAVAL</FONT> and several other algorithms are supported. <STRONG>mhash</STRONG> support <EM> <FONT SIZE=-1>HMAC</FONT> generation</EM> (a mechanism for message authentication using cryptographic hash functions, and is described in rfc2104). <FONT SIZE=-1>HMAC</FONT> can be used to create message digests using a secret key, so that these message digests cannot be regenerated (or replaced) by someone else. <FONT SIZE=-1>A</FONT> key generation mechanism was added to <STRONG>mhash</STRONG> since <EM>key generation</EM> algorithms usually involve hash algorithms.</P> <P> <HR> <H1><A NAME="api functions"> <FONT SIZE=-1>API</FONT> <FONT SIZE=-1>FUNCTIONS</FONT></A></H1> <P>We will describe the <FONT SIZE=-1>API</FONT> of <STRONG>mhash</STRONG> in detail now. The order follows the one in the <FONT SIZE=-1>SYNOPSIS</FONT> directly.</P> <DL> <DT><STRONG><A NAME="item_mhash_count">size_t <STRONG>mhash_count</STRONG>(void);</A></STRONG><BR> <DD> This returns the <CODE>hashid</CODE> of the last available hash. Hashes are numbered from 0 to <A HREF="#item_mhash_count"><CODE>mhash_count()</CODE></A>. <P></P> <DT><STRONG><A NAME="item_mhash_get_block_size">size_t <STRONG>mhash_get_block_size</STRONG>(hashid <EM>type</EM>);</A></STRONG><BR> <DD> If <EM>type</EM> exists, this returns the used blocksize of the hash <EM>type</EM> in bytes. Otherwise, it returns 0. <P></P> <DT><STRONG><A NAME="item_mhash_get_hash_name">char *<STRONG>mhash_get_hash_name</STRONG>(hashid <EM>type</EM>);</A></STRONG><BR> <DD> If <EM>type</EM> exists, this returns the name of the hash <EM>type</EM>. Otherwise, a <CODE>NULL</CODE> pointer is returned. The string is allocated with <CODE>malloc(3)</CODE> seperately, so do not forget to <CODE>free(3)</CODE> it. <P></P> <DT><STRONG><A NAME="item_mhash_get_hash_name_static">const char *<STRONG>mhash_get_hash_name_static</STRONG>(hashid <EM>type</EM>);</A></STRONG><BR> <DD> If <EM>type</EM> exists, this returns the name of the hash <EM>type</EM>. Otherwise, a <CODE>NULL</CODE> pointer is returned. <P></P> <DT><STRONG><A NAME="item_mhash_get_hash_pblock">size_t <STRONG>mhash_get_hash_pblock</STRONG>(hashid <EM>type</EM>);</A></STRONG><BR> <DD> It returns the block size that the algorithm operates. This is used in mhash_hmac_init. If the return value is 0 you shouldn't use that algorithm in <FONT SIZE=-1>HMAC.</FONT> <P></P> <DT><STRONG><A NAME="item_mhash_get_mhash_algo">hashid <STRONG>mhash_get_mhash_algo</STRONG> <FONT SIZE=-1>(MHASH</FONT> <EM>src</EM>);</A></STRONG><BR> <DD> Returns the algorithm used in the state of <EM>src</EM>. <P></P> <DT><STRONG><A NAME="item_mhash_init"> <FONT SIZE=-1>MHASH</FONT> <STRONG>mhash_init</STRONG>(hashid <EM>type</EM>);</A></STRONG><BR> <DD> This setups a context to begin hashing using the algorithm <EM>type</EM>. It returns a descriptor to that context which will result in leaking memory, if you do not call <A HREF="#item_mhash_deinit"><CODE>mhash_deinit(3)</CODE></A> later. Returns <CODE>MHASH_FAILED</CODE> on failure. <P></P> <DT><STRONG><A NAME="item_mhash_hmac_init"> <FONT SIZE=-1>MHASH</FONT> <STRONG>mhash_hmac_init</STRONG>(const hashid <EM>type</EM>, void *<EM>key</EM>, int <EM>keysize</EM>, int <EM>block</EM>);</A></STRONG><BR> <DD> This setups a context to begin hashing using the algorithm type in <FONT SIZE=-1>HMAC</FONT> mode. <EM>key</EM> should be a pointer to the key and <EM>keysize</EM> its len. The <EM>block</EM> is the block size (in bytes) that the algorithm operates. It should be obtained by mhash_get_hash_pblock(). If its 0 it defaults to 64. After calling it you should use <A HREF="#item_mhash"><CODE>mhash()</CODE></A> to update the context. It returns a descriptor to that context which will result in leaking memory, if you do not call <A HREF="#item_mhash_hmac_deinit"><CODE>mhash_hmac_deinit(3)</CODE></A> later. Returns <CODE>MHASH_FAILED</CODE> on failure. <P></P> <DT><STRONG><A NAME="item_mhash_cp"> <FONT SIZE=-1>MHASH</FONT> <STRONG>mhash_cp</STRONG> <FONT SIZE=-1>(MHASH</FONT> <EM>src</EM>);</A></STRONG><BR> <DD> This setups a new context using the state of <EM>src</EM>. <P></P> <DT><STRONG><A NAME="item_mhash">int <STRONG>mhash</STRONG> <FONT SIZE=-1>(MHASH</FONT> <EM>thread</EM>, const void *<EM>plaintext</EM>, size_t <EM>size</EM>);</A></STRONG><BR> <DD> This updates the context described by <EM>thread</EM> with <EM>plaintext</EM>. <EM>size</EM> is the length of <EM>plaintext</EM> which may be binary data. <P></P> <DT><STRONG><A NAME="item_mhash_save_state_mem">int <STRONG>mhash_save_state_mem</STRONG>( <FONT SIZE=-1>MHASH</FONT> <EM>thread</EM>, void *<EM>mem</EM>, int* <EM>mem_size</EM>);</A></STRONG><BR> <DD> Saves the state of a hashing algorithm such that it can be restored at some later point in time using <STRONG>mhash_restore_state_mem</STRONG>(). <EM>mem_size</EM> should contain the size of the given <EM>mem</EM> pointer. If it is not enough to hold the buffer the required value will be copied there. <P></P> <DT><STRONG><A NAME="item_mhash_restore_state_mem"> <FONT SIZE=-1>MHASH</FONT> <STRONG>mhash_restore_state_mem</STRONG>(void* <EM>mem</EM>);</A></STRONG><BR> <DD> Restores the state of a hashing algorithm that was saved using <STRONG>mhash_save_state_mem</STRONG>(). Use like <STRONG>mhash_init</STRONG>(). <P></P> <DT><STRONG><A NAME="item_mhash_end">void *<STRONG>mhash_end</STRONG> <FONT SIZE=-1>(MHASH</FONT> <EM>thread</EM>);</A></STRONG><BR> <DD> This frees all resources associated with <EM>thread</EM> and returns the result of the whole hashing operation (the ``<EM>digest</EM>''). <P></P> <DT><STRONG><A NAME="item_mhash_deinit">void <STRONG>mhash_deinit</STRONG> <FONT SIZE=-1>(MHASH</FONT> <EM>thread</EM>, void* digest);</A></STRONG><BR> <DD> This frees all resources associated with <EM>thread</EM> and stores the result of the whole hashing operation in memory pointed by digest. <P></P> <DT><STRONG><A NAME="item_mhash_hmac_end">void *<STRONG>mhash_hmac_end</STRONG> <FONT SIZE=-1>(MHASH</FONT> <EM>thread</EM>);</A></STRONG><BR> <DD> This frees all resources associated with thread and returns the result of the whole hashing operation (the ``<EM>mac</EM>''). <P></P> <DT><STRONG><A NAME="item_mhash_hmac_deinit">int <STRONG>mhash_hmac_deinit</STRONG> <FONT SIZE=-1>(MHASH</FONT> <EM>thread</EM>, void* digest);</A></STRONG><BR> <DD> This frees all resources associated with <EM>thread</EM> and stores the result of the whole hashing operation in memory pointed by digest. Returns non-zero in case of an error; <P></P> <DT><STRONG><A NAME="item_mhash_end_m">void *<STRONG>mhash_end_m</STRONG> <FONT SIZE=-1>(MHASH</FONT> <EM>thread</EM>, void* (*hash_malloc)(size_t));</A></STRONG><BR> <DD> This frees all resources associated with <EM>thread</EM> and returns the result of the whole hashing operation (the ``<EM>digest</EM>''). The result will be allocated by using the <CODE>hash_malloc()</CODE> function provided. <P></P> <DT><STRONG>void *<STRONG>mhash_hmac_end</STRONG> <FONT SIZE=-1>(MHASH</FONT> <EM>thread</EM>, void* (*hash_malloc)(size_t));</STRONG><BR> <DD> This frees all resources associated with thread and returns the result of the whole hashing operation (the ``<EM>mac</EM>''). The result will be allocated by using the <CODE>hash_malloc()</CODE> function provided. <P></P></DL> <P> <HR> <H1><A NAME="keygen api functions"> <FONT SIZE=-1>KEYGEN</FONT> <FONT SIZE=-1>API</FONT> <FONT SIZE=-1>FUNCTIONS</FONT></A></H1> <P>We will now describe the Key Generation <FONT SIZE=-1>API</FONT> of <STRONG>mhash</STRONG> in detail.</P> <DL> <DT><STRONG><A NAME="item_mhash_keygen_ext">int <STRONG>mhash_keygen_ext</STRONG>(keygenid <EM>algorithm</EM>, <FONT SIZE=-1>KEYGEN</FONT> <EM>algorithm_data</EM>, void* <EM>keyword</EM>, int <EM>keysize</EM>, unsigned char* <EM>password</EM>, int <EM>passwordlen</EM>);</A></STRONG><BR> <DD> This function, generates a key from a password. The password is read from <EM>password</EM> and it's len should be in <EM>passwordlen</EM>. The key generation algorithm is specified in <EM>algorithm</EM>, and that algorithm may (internally) use the <FONT SIZE=-1>KEYGEN</FONT> structure. The <FONT SIZE=-1>KEYGEN</FONT> structure consists of: typedef struct keygen { hashid hash_algorithm[2]; unsigned int count; void* salt; int salt_size; } <FONT SIZE=-1>KEYGEN;</FONT> <P>The <CODE>algorithm(s)</CODE> specified in <EM>algorithm_data.hash_algorithm</EM>, should be hash algorithms and may be used by the key generation algorithm. Some key generation algorithms may use more than one hash algorithms (view also mhash_keygen_uses_hash_algorithm()). If it is desirable (and supported by the algorithm, eg. <FONT SIZE=-1>KEYGEN_S2K_SALTED)</FONT> a salt may be specified in <EM>algorithm_data.salt</EM> of size <EM>algorithm_data.salt_size</EM> or may be <FONT SIZE=-1>NULL.</FONT></P> <P>The algorithm may use the <EM>algorithm_data.count</EM> internally (eg. <FONT SIZE=-1>KEYGEN_S2K_ISALTED).</FONT> The generated keyword is stored in <EM>keyword</EM>, which should be (at least) <EM>keysize</EM> bytes long. The generated keyword is a binary one.</P> <P></P> <DT><STRONG><A NAME="item_mhash_keygen_uses_salt">int <STRONG>mhash_keygen_uses_salt</STRONG>( keygenid <EM>algorithm</EM>);</A></STRONG><BR> <DD> This function returns 1 if the specified key generation algorithm needs a salt to be specified. <P></P> <DT><STRONG><A NAME="item_mhash_keygen_uses_count">int <STRONG>mhash_keygen_uses_count</STRONG>( keygenid <EM>algorithm</EM>);</A></STRONG><BR> <DD> This function returns 1 if the specified key generation algorithm needs the algorithm_data.count field in mhash_keygen_ext(). The count field tells the algorithm to hash repeatedly the password and to stop when <STRONG>count</STRONG> bytes have been processed. <P></P> <DT><STRONG><A NAME="item_mhash_get_keygen_salt_size">int <STRONG>mhash_get_keygen_salt_size</STRONG>( keygenid <EM>algorithm</EM>);</A></STRONG><BR> <DD> This function returns the size of the salt size, that the specific <EM>algorithm</EM> will use. If it returns 0, then there is no limitation in the size. <P></P> <DT><STRONG><A NAME="item_mhash_get_keygen_max_key_size">int <STRONG>mhash_get_keygen_max_key_size</STRONG>( keygenid <EM>algorithm</EM>);</A></STRONG><BR> <DD> This function returns the maximum size of the key, that the key generation algorithm may produce. If it returns 0, then there is no limitation in the size. <P></P> <DT><STRONG><A NAME="item_mhash_keygen_uses_hash_algorithm">int <STRONG>mhash_keygen_uses_hash_algorithm</STRONG>( keygenid <EM>algorithm</EM>);</A></STRONG><BR> <DD> This function returns the number of the hash algorithms the key generation algorithm will use. If it is 0 then no hash algorithm is used by the key generation algorithm. This is for the <EM>algorithm_data.hash_algorithm</EM> field in mhash_keygen_ext(). If <P></P> <DT><STRONG><A NAME="item_mhash_keygen_count">size_t <STRONG>mhash_keygen_count</STRONG>(void);</A></STRONG><BR> <DD> This returns the <CODE>keygenid</CODE> of the last available key generation algorithm. Algorithms are numbered from 0 to <A HREF="#item_mhash_keygen_count"><CODE>mhash_keygen_count()</CODE></A>. <P></P> <DT><STRONG><A NAME="item_mhash_get_keygen_name">char *<STRONG>mhash_get_keygen_name</STRONG>(keygenid <EM>type</EM>);</A></STRONG><BR> <DD> If <EM>type</EM> exists, this returns the name of the keygen <EM>type</EM>. Otherwise, a <CODE>NULL</CODE> pointer is returned. The string is allocated with <CODE>malloc(3)</CODE> seperately, so do not forget to <CODE>free(3)</CODE> it. <P></P> <DT><STRONG><A NAME="item_mhash_get_keygen_name_static">const char *<STRONG>mhash_get_keygen_name_static</STRONG>(keygenid <EM>type</EM>);</A></STRONG><BR> <DD> If <EM>type</EM> exists, this returns the name of the keygen <EM>type</EM>. Otherwise, a <CODE>NULL</CODE> pointer is returned. <P></P></DL> <P> <HR> <H1><A NAME="example"> <FONT SIZE=-1>EXAMPLE</FONT></A></H1> <P>Hashing <FONT SIZE=-1>STDIN</FONT> until <FONT SIZE=-1>EOF.</FONT></P> <PRE> #include <mhash.h> #include <stdio.h> #include <stdlib.h></PRE> <PRE> int main(void) { int i; MHASH td; unsigned char buffer; unsigned char *hash;</PRE> <PRE> td = mhash_init(MHASH_MD5);</PRE> <PRE> if (td == MHASH_FAILED) exit(1);</PRE> <PRE> while (fread(&buffer, 1, 1, stdin) == 1) { mhash(td, &buffer, 1); }</PRE> <PRE> hash = mhash_end(td);</PRE> <PRE> printf("Hash:"); for (i = 0; i < mhash_get_block_size(MHASH_MD5); i++) { printf("%.2x", hash[i]); } printf("\n");</PRE> <PRE> exit(0); }</PRE> <P> <HR> <H1><A NAME="example"> <FONT SIZE=-1>EXAMPLE</FONT></A></H1> <P>An example program using <FONT SIZE=-1>HMAC:</FONT></P> <PRE> #include <mhash.h> #include <stdio.h></PRE> <PRE> int main() {</PRE> <PRE> char password[] = "Jefe"; int keylen = 4; char data[] = "what do ya want for nothing?"; int datalen = 28; MHASH td; unsigned char *mac; int j; </PRE> <PRE> td = mhash_hmac_init(MHASH_MD5, password, keylen, mhash_get_hash_pblock(MHASH_MD5));</PRE> <PRE> mhash(td, data, datalen); mac = mhash_hmac_end(td);</PRE> <PRE> /* * The output should be 0x750c783e6ab0b503eaa86e310a5db738 * according to RFC 2104. */</PRE> <PRE> printf("0x"); for (j = 0; j < mhash_get_block_size(MHASH_MD5); j++) { printf("%.2x", mac[j]); } printf("\n"); </PRE> <PRE> exit(0); }</PRE> <P> <HR> <H1><A NAME="history"> <FONT SIZE=-1>HISTORY</FONT></A></H1> <P>This library was originally written by <EM>Nikos Mavroyanopoulos</EM> <<A HREF="mailto:nmav@hellug.gr">nmav@hellug.gr</A>> who passed the project over to <EM>Sascha Schumann</EM> <<A HREF="mailto:sascha@schumann.cx">sascha@schumann.cx</A>> in May 1999. Sascha maintained it until March 2000. The library is now maintained by <EM>Nikos Mavroyanopoulos</EM>.</P> <P> <HR> <H1><A NAME="bugs"> <FONT SIZE=-1>BUGS</FONT></A></H1> <P>If you find any, please send a bug report (preferrably together with a patch) to the maintainer with a detailed description on how to reproduce the bug.</P> <P> <HR> <H1><A NAME="authors"> <FONT SIZE=-1>AUTHORS</FONT></A></H1> <P>Sascha Schumann <<A HREF="mailto:sascha@schumann.cx">sascha@schumann.cx</A>> Nikos Mavroyanopoulos <<A HREF="mailto:nmav@hellug.gr">nmav@hellug.gr</A>></P> </BODY> </HTML>