Since a websocket handshake hashes only 16 bytes you don't need an implementation that provides incremental updates. The attached SHA1 is slower than the openssl implementation, but quite short. Just in case.
-------- Weitergeleitete Nachricht -------- Von: "Gausmann, David" <david.gausm...@measx.com> Antwort an: libmicrohttpd development and user mailinglist < libmicrohttpd@gnu.org> An: libmicrohttpd@gnu.org <libmicrohttpd@gnu.org> Betreff: [libmicrohttpd] Update for websocket library Datum: Sun, 17 Oct 2021 18:20:17 +0000 Hi @all, some months ago I wrote an additional library for libmicrohttpd to add support for the websocket protocol.Christian and Evgeny added that library with the configure flag “--with-experimental”.There were still some tasks to do, but now I am finally done with them. In the attachment you find the patch file, which must be applied to get the final version of the API. For short it contains the following changes:- added API documentation to libmicrohttpd.texi- added websocket tutorial chapter to libmicrohttpd-tutorial and an much easier example for the tutorial- added additional helper functions to ease the HTTP websocket handshake- the code can now be compiled on Linux without errors :-)- changed sha1.c and sha1.h to the files provided by Evgeny (I replaced those files in src/microhttpd_ws/ with the files from src/microhttpd/ - maybe there is a smarter way...?)- removed dependency for "htons" and "htonl" (these functions are now implemented in MHD_websocket.c; no need for OS-dependent files anymore)- added an additional test script for testing of the library with any webbrowser (for manual practice test)- several bugfixes- parameters renamed- special things clarified (fragmentation, RNG for client mode) The new version of the API is at some points incompatible with the old version, but since it was in an experimental phase and it didn't compile on Linux, I guess this shouldn't bother anyone.From my point of view, I am now finished with the library and it could go out of experimental.Maybe it would be good if anyone could give it a review. Kind RegardsDavid Gausmann measX GmbH & Co. KG David GausmannFachinformatiker Anwendungsentwicklung | Testdatenmanagement und AuswertesystemeBüro: Aachen (Pascalstraße 67, 52076 Aachen-Oberforstbach)Telefon: +49 (0) 2166 9520-170E- Mail: david.gausm...@measx.com | Web: https://www.measx.com measX GmbH & Co. KG | Trompeterallee 110 | 41189 Mönchengladbach | Germany | Telefon: +49 (0) 2166 9520-0 | Fax: +49 (0) 2166 9520-20Sitz der Gesellschaft: Mönchengladbach | Registergericht: AG Mönchengladbach (HRA 5623) | USt-IdNr: DE 814281560Geschäftsführer: Dr. Joachim Hilsmann | Stadtsparkasse Mönchengladbach IBAN: DE84310500000000276600 | BIC-Swift: MG LS DE 33Persönlich haftende Gesellschafterin: measX Verwaltungsgesellschaft mbH | Registergericht: AG Mönchengladbach (HRB 10947)_________________________________________________________________ _________________________________________________
void sha1_encode( const uint8_t *data, size_t databytes, uint8_t digest[20] ) { uint64_t i, loopcount, databits, tailbytes; uint8_t datatail[128] = {0}; uint32_t H[] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; uint32_t W[80]; uint64_t idx, widx, didx = 0; /* Pre-processing of data tail (includes padding to fill out 512-bit chunk): Add bit '1' to end of message (big-endian) Add 64-bit message length in bits at very end (big-endian) */ loopcount = (databytes + 8) / 64 + 1; databits = databytes * 8; tailbytes = 64 * loopcount - databytes; datatail[0] = 0x80; datatail[tailbytes - 8] = uint8_t((databits >> 56) & 0xFF); datatail[tailbytes - 7] = uint8_t((databits >> 48) & 0xFF); datatail[tailbytes - 6] = uint8_t((databits >> 40) & 0xFF); datatail[tailbytes - 5] = uint8_t((databits >> 32) & 0xFF); datatail[tailbytes - 4] = uint8_t((databits >> 24) & 0xFF); datatail[tailbytes - 3] = uint8_t((databits >> 16) & 0xFF); datatail[tailbytes - 2] = uint8_t((databits >> 8) & 0xFF); datatail[tailbytes - 1] = uint8_t((databits >> 0) & 0xFF); /* Process each 512-bit chunk */ for( i=0; i < loopcount; ++i ) { uint32_t a = H[0]; uint32_t b = H[1]; uint32_t c = H[2]; uint32_t d = H[3]; uint32_t e = H[4]; uint32_t f=0, k=0, temp; /* Compute all elements in W */ memset( W, 0, 80 * sizeof(uint32_t) ); /* Break 512-bit chunk into sixteen 32-bit, big endian words */ for( widx=0; widx <= 15; ++widx ) { int wcount = 24; /* Copy byte-per byte from specified buffer */ while( didx < databytes && wcount >= 0 ) { W[widx] += (((uint32_t)data[didx]) << wcount); didx++; wcount -= 8; } /* Fill out W with padding as needed */ while( wcount >= 0 ) { W[widx] += (((uint32_t)datatail[didx - databytes]) << wcount); didx++; wcount -= 8; } } /* Extend the sixteen 32-bit words into eighty 32-bit words, with potential optimization from: "Improving the Performance of the Secure Hash Algorithm (SHA-1)" by Max Locktyukhin */ #define SHA1ROTATELEFT(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) for( widx = 16; widx <= 31; ++widx ) { W[widx] = SHA1ROTATELEFT( (W[widx - 3] ^ W[widx - 8] ^ W[widx - 14] ^ W[widx - 16]), 1 ); } for( widx = 32; widx <= 79; ++widx ) { W[widx] = SHA1ROTATELEFT( (W[widx - 6] ^ W[widx - 16] ^ W[widx - 28] ^ W[widx - 32]), 2 ); } /* Main loop */ for( idx=0; idx <= 79; ++idx ) { if( idx <= 19 ) { f = (b & c) | ((~b) & d); k = 0x5A827999; } else if( idx >= 20 && idx <= 39 ) { f = b ^ c ^ d; k = 0x6ED9EBA1; } else if( idx >= 40 && idx <= 59 ) { f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC; } else if( idx >= 60 && idx <= 79 ) { f = b ^ c ^ d; k = 0xCA62C1D6; } temp = SHA1ROTATELEFT(a, 5) + f + e + k + W[idx]; e = d; d = c; c = SHA1ROTATELEFT(b, 30); b = a; a = temp; } H[0] += a; H[1] += b; H[2] += c; H[3] += d; H[4] += e; } /* Store binary digest in supplied buffer */ for( i=0; i < 5; ++i ) { digest[i * 4 + 0] = (uint8_t) (H[i] >> 24); digest[i * 4 + 1] = (uint8_t) (H[i] >> 16); digest[i * 4 + 2] = (uint8_t) (H[i] >> 8); digest[i * 4 + 3] = (uint8_t) (H[i]); } }