Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package ghc-cryptohash-md5 for openSUSE:Factory checked in at 2021-11-11 21:36:23 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-cryptohash-md5 (Old) and /work/SRC/openSUSE:Factory/.ghc-cryptohash-md5.new.1890 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-cryptohash-md5" Thu Nov 11 21:36:23 2021 rev:6 rq:930321 version:0.11.101.0 Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-cryptohash-md5/ghc-cryptohash-md5.changes 2021-06-23 17:38:24.576486144 +0200 +++ /work/SRC/openSUSE:Factory/.ghc-cryptohash-md5.new.1890/ghc-cryptohash-md5.changes 2021-11-11 21:36:36.960897141 +0100 @@ -1,0 +2,19 @@ +Mon Nov 1 08:22:10 UTC 2021 - [email protected] + +- Update cryptohash-md5 to version 0.11.101.0. + ## 0.11.101.0 + + - Add `Eq` instance for `Ctx` + - Add `start` and `startlazy` producing `Ctx` + - Remove ineffective RULES + - Declare `Crypto.Hash.MD5` module `-XTrustworthy` + - Convert to `CApiFFI` + - Added `...AndLength` variants of hashing functions: + + - `finalizeAndLength` + - `hashlazyAndLength` + - `hmaclazyAndLength` + + - Minor optimizations in `hmac` and `hash` + +------------------------------------------------------------------- Old: ---- cryptohash-md5-0.11.100.1.tar.gz cryptohash-md5.cabal New: ---- cryptohash-md5-0.11.101.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-cryptohash-md5.spec ++++++ --- /var/tmp/diff_new_pack.qOaKqf/_old 2021-11-11 21:36:37.460897506 +0100 +++ /var/tmp/diff_new_pack.qOaKqf/_new 2021-11-11 21:36:37.464897509 +0100 @@ -19,13 +19,12 @@ %global pkg_name cryptohash-md5 %bcond_with tests Name: ghc-%{pkg_name} -Version: 0.11.100.1 +Version: 0.11.101.0 Release: 0 Summary: Fast, pure and practical MD5 implementation License: BSD-3-Clause URL: https://hackage.haskell.org/package/%{pkg_name} Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{version}.tar.gz -Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/6.cabal#/%{pkg_name}.cabal BuildRequires: ghc-Cabal-devel BuildRequires: ghc-bytestring-devel BuildRequires: ghc-rpm-macros @@ -47,31 +46,14 @@ The implementation is made in C with a haskell FFI wrapper that hides the C implementation. -If, instead, you require a pure Haskell implementation and performance is -secondary, please refer to the [pureMD5 -package](https://hackage.haskell.org/package/pureMD5). - -=== Packages in the 'cryptohash-*' family - -- <https://hackage.haskell.org/package/cryptohash-md5 cryptohash-md5> - -<https://hackage.haskell.org/package/cryptohash-sha1 cryptohash-sha1> - -<https://hackage.haskell.org/package/cryptohash-sha256 cryptohash-sha256> - -<https://hackage.haskell.org/package/cryptohash-sha512 cryptohash-sha512> - -=== Relationship to the 'cryptohash' package and its API - -This package has been originally a fork of 'cryptohash-0.11.7' because the -'cryptohash' package had been deprecated and so this package continues to +NOTE: This package has been forked off 'cryptohash-0.11.7' because the +'cryptohash' package has been deprecated and so this package continues to satisfy the need for a lightweight package providing the MD5 hash algorithm without any dependencies on packages other than 'base' and 'bytestring'. -The API exposed by 'cryptohash-md5-0.11.*''s "Crypto.Hash.MD5" module is -guaranteed to remain a compatible superset of the API provided by the -'cryptohash-0.11.7''s module of the same name. - -Consequently, this package is designed to be used as a drop-in replacement for -'cryptohash-0.11.7''s "Crypto.Hash.MD5" module, though with a [clearly smaller -footprint by almost 3 orders of -magnitude](https://www.reddit.com/r/haskell/comments/5lxv75/psa_please_use_unique_module_names_when_uploading/dbzegx3/). + +Consequently, this package can be used as a drop-in replacement for +'cryptohash''s "Crypto.Hash.MD5" module, though with a clearly smaller +footprint. %package devel Summary: Haskell %{pkg_name} library development files @@ -85,7 +67,6 @@ %prep %autosetup -n %{pkg_name}-%{version} -cp -p %{SOURCE1} %{pkg_name}.cabal %build %ghc_lib_build ++++++ cryptohash-md5-0.11.100.1.tar.gz -> cryptohash-md5-0.11.101.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptohash-md5-0.11.100.1/cbits/md5.c new/cryptohash-md5-0.11.101.0/cbits/md5.c --- old/cryptohash-md5-0.11.100.1/cbits/md5.c 2016-06-28 09:14:08.000000000 +0200 +++ new/cryptohash-md5-0.11.101.0/cbits/md5.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,250 +0,0 @@ -/* - * Copyright (C) 2006-2009 Vincent Hanquez <[email protected]> - * 2016 Herbert Valerio Riedel <[email protected]> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "md5.h" - -#include <assert.h> -#include <string.h> -#include <ghcautoconf.h> - -#if defined(static_assert) -static_assert(sizeof(struct md5_ctx) == MD5_CTX_SIZE, "unexpected md5_ctx size"); -#else -/* poor man's pre-C11 _Static_assert */ -typedef char static_assertion__unexpected_md5_ctx_size[(sizeof(struct md5_ctx) == MD5_CTX_SIZE)?1:-1]; -#endif - -#define ptr_uint32_aligned(ptr) (!((uintptr_t)(ptr) & 0x3)) - -static inline uint32_t -rol32(const uint32_t word, const unsigned shift) -{ - /* GCC usually transforms this into a 'rol'-insn */ - return (word << shift) | (word >> (32 - shift)); -} - -static inline uint32_t -cpu_to_le32(const uint32_t hl) -{ -#if !WORDS_BIGENDIAN - return hl; -#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) - return __builtin_bswap32(hl); -#else - /* GCC usually transforms this into a bswap insn */ - return ((hl & 0xff000000) >> 24) | - ((hl & 0x00ff0000) >> 8) | - ((hl & 0x0000ff00) << 8) | - ( hl << 24); -#endif -} - -static inline void -cpu_to_le32_array(uint32_t *dest, const uint32_t *src, unsigned wordcnt) -{ - while (wordcnt--) - *dest++ = cpu_to_le32(*src++); -} - -static inline uint64_t -cpu_to_le64(const uint64_t hll) -{ -#if !WORDS_BIGENDIAN - return hll; -#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) - return __builtin_bswap64(hll); -#else - return ((uint64_t)cpu_to_le32(hll & 0xffffffff) << 32LL) | cpu_to_le32(hll >> 32); -#endif -} - - -void -hs_cryptohash_md5_init(struct md5_ctx *ctx) -{ - memset(ctx, 0, sizeof(*ctx)); - - ctx->h[0] = 0x67452301; - ctx->h[1] = 0xefcdab89; - ctx->h[2] = 0x98badcfe; - ctx->h[3] = 0x10325476; -} - -#define f1(x, y, z) (z ^ (x & (y ^ z))) -#define f2(x, y, z) f1(z, x, y) -#define f3(x, y, z) (x ^ y ^ z) -#define f4(x, y, z) (y ^ (x | ~z)) -#define R(f, a, b, c, d, i, k, s) a += f(b, c, d) + w[i] + k; a = rol32(a, s); a += b - -static void -md5_do_chunk_aligned(struct md5_ctx *ctx, const uint32_t w[]) -{ - uint32_t a = ctx->h[0]; - uint32_t b = ctx->h[1]; - uint32_t c = ctx->h[2]; - uint32_t d = ctx->h[3]; - - R(f1, a, b, c, d, 0, 0xd76aa478, 7); - R(f1, d, a, b, c, 1, 0xe8c7b756, 12); - R(f1, c, d, a, b, 2, 0x242070db, 17); - R(f1, b, c, d, a, 3, 0xc1bdceee, 22); - R(f1, a, b, c, d, 4, 0xf57c0faf, 7); - R(f1, d, a, b, c, 5, 0x4787c62a, 12); - R(f1, c, d, a, b, 6, 0xa8304613, 17); - R(f1, b, c, d, a, 7, 0xfd469501, 22); - R(f1, a, b, c, d, 8, 0x698098d8, 7); - R(f1, d, a, b, c, 9, 0x8b44f7af, 12); - R(f1, c, d, a, b, 10, 0xffff5bb1, 17); - R(f1, b, c, d, a, 11, 0x895cd7be, 22); - R(f1, a, b, c, d, 12, 0x6b901122, 7); - R(f1, d, a, b, c, 13, 0xfd987193, 12); - R(f1, c, d, a, b, 14, 0xa679438e, 17); - R(f1, b, c, d, a, 15, 0x49b40821, 22); - - R(f2, a, b, c, d, 1, 0xf61e2562, 5); - R(f2, d, a, b, c, 6, 0xc040b340, 9); - R(f2, c, d, a, b, 11, 0x265e5a51, 14); - R(f2, b, c, d, a, 0, 0xe9b6c7aa, 20); - R(f2, a, b, c, d, 5, 0xd62f105d, 5); - R(f2, d, a, b, c, 10, 0x02441453, 9); - R(f2, c, d, a, b, 15, 0xd8a1e681, 14); - R(f2, b, c, d, a, 4, 0xe7d3fbc8, 20); - R(f2, a, b, c, d, 9, 0x21e1cde6, 5); - R(f2, d, a, b, c, 14, 0xc33707d6, 9); - R(f2, c, d, a, b, 3, 0xf4d50d87, 14); - R(f2, b, c, d, a, 8, 0x455a14ed, 20); - R(f2, a, b, c, d, 13, 0xa9e3e905, 5); - R(f2, d, a, b, c, 2, 0xfcefa3f8, 9); - R(f2, c, d, a, b, 7, 0x676f02d9, 14); - R(f2, b, c, d, a, 12, 0x8d2a4c8a, 20); - - R(f3, a, b, c, d, 5, 0xfffa3942, 4); - R(f3, d, a, b, c, 8, 0x8771f681, 11); - R(f3, c, d, a, b, 11, 0x6d9d6122, 16); - R(f3, b, c, d, a, 14, 0xfde5380c, 23); - R(f3, a, b, c, d, 1, 0xa4beea44, 4); - R(f3, d, a, b, c, 4, 0x4bdecfa9, 11); - R(f3, c, d, a, b, 7, 0xf6bb4b60, 16); - R(f3, b, c, d, a, 10, 0xbebfbc70, 23); - R(f3, a, b, c, d, 13, 0x289b7ec6, 4); - R(f3, d, a, b, c, 0, 0xeaa127fa, 11); - R(f3, c, d, a, b, 3, 0xd4ef3085, 16); - R(f3, b, c, d, a, 6, 0x04881d05, 23); - R(f3, a, b, c, d, 9, 0xd9d4d039, 4); - R(f3, d, a, b, c, 12, 0xe6db99e5, 11); - R(f3, c, d, a, b, 15, 0x1fa27cf8, 16); - R(f3, b, c, d, a, 2, 0xc4ac5665, 23); - - R(f4, a, b, c, d, 0, 0xf4292244, 6); - R(f4, d, a, b, c, 7, 0x432aff97, 10); - R(f4, c, d, a, b, 14, 0xab9423a7, 15); - R(f4, b, c, d, a, 5, 0xfc93a039, 21); - R(f4, a, b, c, d, 12, 0x655b59c3, 6); - R(f4, d, a, b, c, 3, 0x8f0ccc92, 10); - R(f4, c, d, a, b, 10, 0xffeff47d, 15); - R(f4, b, c, d, a, 1, 0x85845dd1, 21); - R(f4, a, b, c, d, 8, 0x6fa87e4f, 6); - R(f4, d, a, b, c, 15, 0xfe2ce6e0, 10); - R(f4, c, d, a, b, 6, 0xa3014314, 15); - R(f4, b, c, d, a, 13, 0x4e0811a1, 21); - R(f4, a, b, c, d, 4, 0xf7537e82, 6); - R(f4, d, a, b, c, 11, 0xbd3af235, 10); - R(f4, c, d, a, b, 2, 0x2ad7d2bb, 15); - R(f4, b, c, d, a, 9, 0xeb86d391, 21); - - ctx->h[0] += a; - ctx->h[1] += b; - ctx->h[2] += c; - ctx->h[3] += d; -} - -static void -md5_do_chunk(struct md5_ctx *ctx, const uint8_t buf[]) -{ - if (ptr_uint32_aligned(buf)) { /* aligned buf */ -#if WORDS_BIGENDIAN - uint32_t w[16]; cpu_to_le32_array(w, (const uint32_t *)buf, 16); -#else - const uint32_t *w = (const uint32_t *)buf; -#endif - md5_do_chunk_aligned(ctx, w); - } else { /* unaligned buf */ - uint32_t w[16]; memcpy(w, buf, 64); -#if WORDS_BIGENDIAN - cpu_to_le32_array(w, w, 16); -#endif - md5_do_chunk_aligned(ctx, w); - } -} - -void -hs_cryptohash_md5_update(struct md5_ctx *ctx, const uint8_t *data, size_t len) -{ - size_t index = ctx->sz & 0x3f; - const size_t to_fill = 64 - index; - - ctx->sz += len; - - /* process partial buffer if there's enough data to make a block */ - if (index && len >= to_fill) { - memcpy(ctx->buf + index, data, to_fill); - md5_do_chunk(ctx, ctx->buf); - /* memset(ctx->buf, 0, 64); */ - len -= to_fill; - data += to_fill; - index = 0; - } - - /* process as many 64-blocks as possible */ - while (len >= 64) { - md5_do_chunk(ctx, data); - len -= 64; - data += 64; - } - - /* append data into buf */ - if (len) - memcpy(ctx->buf + index, data, len); -} - -void -hs_cryptohash_md5_finalize(struct md5_ctx *ctx, uint8_t *out) -{ - static const uint8_t padding[64] = { 0x80, }; - - /* add padding and update data with it */ - const uint64_t bits = cpu_to_le64(ctx->sz << 3); - - /* pad out to 56 */ - const size_t index = (ctx->sz & 0x3f); - const size_t padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); - hs_cryptohash_md5_update(ctx, padding, padlen); - - /* append length */ - hs_cryptohash_md5_update(ctx, (const uint8_t *) &bits, sizeof(bits)); - - /* output hash */ - cpu_to_le32_array((uint32_t *) out, ctx->h, 4); -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptohash-md5-0.11.100.1/cbits/md5.h new/cryptohash-md5-0.11.101.0/cbits/md5.h --- old/cryptohash-md5-0.11.100.1/cbits/md5.h 2016-06-28 09:14:08.000000000 +0200 +++ new/cryptohash-md5-0.11.101.0/cbits/md5.h 2001-09-09 03:46:40.000000000 +0200 @@ -28,6 +28,9 @@ #include <stdint.h> #include <stddef.h> +#include <assert.h> +#include <string.h> +#include <ghcautoconf.h> struct md5_ctx { @@ -39,8 +42,243 @@ #define MD5_DIGEST_SIZE 16 #define MD5_CTX_SIZE 88 -void hs_cryptohash_md5_init(struct md5_ctx *ctx); -void hs_cryptohash_md5_update(struct md5_ctx *ctx, const uint8_t *data, size_t len); -void hs_cryptohash_md5_finalize(struct md5_ctx *ctx, uint8_t *out); +static inline void hs_cryptohash_md5_init(struct md5_ctx *ctx); +static inline void hs_cryptohash_md5_update(struct md5_ctx *ctx, const uint8_t *data, size_t len); +static inline uint64_t hs_cryptohash_md5_finalize(struct md5_ctx *ctx, uint8_t *out); + +#if defined(static_assert) +static_assert(sizeof(struct md5_ctx) == MD5_CTX_SIZE, "unexpected md5_ctx size"); +#else +/* poor man's pre-C11 _Static_assert */ +typedef char static_assertion__unexpected_md5_ctx_size[(sizeof(struct md5_ctx) == MD5_CTX_SIZE)?1:-1]; +#endif + +#define ptr_uint32_aligned(ptr) (!((uintptr_t)(ptr) & 0x3)) + +static inline uint32_t +rol32(const uint32_t word, const unsigned shift) +{ + /* GCC usually transforms this into a 'rol'-insn */ + return (word << shift) | (word >> (32 - shift)); +} + +static inline uint32_t +cpu_to_le32(const uint32_t hl) +{ +#if !WORDS_BIGENDIAN + return hl; +#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) + return __builtin_bswap32(hl); +#else + /* GCC usually transforms this into a bswap insn */ + return ((hl & 0xff000000) >> 24) | + ((hl & 0x00ff0000) >> 8) | + ((hl & 0x0000ff00) << 8) | + ( hl << 24); +#endif +} + +static inline void +cpu_to_le32_array(uint32_t *dest, const uint32_t *src, unsigned wordcnt) +{ + while (wordcnt--) + *dest++ = cpu_to_le32(*src++); +} + +static inline uint64_t +cpu_to_le64(const uint64_t hll) +{ +#if !WORDS_BIGENDIAN + return hll; +#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) + return __builtin_bswap64(hll); +#else + return ((uint64_t)cpu_to_le32(hll & 0xffffffff) << 32LL) | cpu_to_le32(hll >> 32); +#endif +} + + +static inline void +hs_cryptohash_md5_init(struct md5_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->h[0] = 0x67452301; + ctx->h[1] = 0xefcdab89; + ctx->h[2] = 0x98badcfe; + ctx->h[3] = 0x10325476; +} + +#define f1(x, y, z) (z ^ (x & (y ^ z))) +#define f2(x, y, z) f1(z, x, y) +#define f3(x, y, z) (x ^ y ^ z) +#define f4(x, y, z) (y ^ (x | ~z)) +#define R(f, a, b, c, d, i, k, s) a += f(b, c, d) + w[i] + k; a = rol32(a, s); a += b + +static void +md5_do_chunk_aligned(struct md5_ctx *ctx, const uint32_t w[]) +{ + uint32_t a = ctx->h[0]; + uint32_t b = ctx->h[1]; + uint32_t c = ctx->h[2]; + uint32_t d = ctx->h[3]; + + R(f1, a, b, c, d, 0, 0xd76aa478, 7); + R(f1, d, a, b, c, 1, 0xe8c7b756, 12); + R(f1, c, d, a, b, 2, 0x242070db, 17); + R(f1, b, c, d, a, 3, 0xc1bdceee, 22); + R(f1, a, b, c, d, 4, 0xf57c0faf, 7); + R(f1, d, a, b, c, 5, 0x4787c62a, 12); + R(f1, c, d, a, b, 6, 0xa8304613, 17); + R(f1, b, c, d, a, 7, 0xfd469501, 22); + R(f1, a, b, c, d, 8, 0x698098d8, 7); + R(f1, d, a, b, c, 9, 0x8b44f7af, 12); + R(f1, c, d, a, b, 10, 0xffff5bb1, 17); + R(f1, b, c, d, a, 11, 0x895cd7be, 22); + R(f1, a, b, c, d, 12, 0x6b901122, 7); + R(f1, d, a, b, c, 13, 0xfd987193, 12); + R(f1, c, d, a, b, 14, 0xa679438e, 17); + R(f1, b, c, d, a, 15, 0x49b40821, 22); + + R(f2, a, b, c, d, 1, 0xf61e2562, 5); + R(f2, d, a, b, c, 6, 0xc040b340, 9); + R(f2, c, d, a, b, 11, 0x265e5a51, 14); + R(f2, b, c, d, a, 0, 0xe9b6c7aa, 20); + R(f2, a, b, c, d, 5, 0xd62f105d, 5); + R(f2, d, a, b, c, 10, 0x02441453, 9); + R(f2, c, d, a, b, 15, 0xd8a1e681, 14); + R(f2, b, c, d, a, 4, 0xe7d3fbc8, 20); + R(f2, a, b, c, d, 9, 0x21e1cde6, 5); + R(f2, d, a, b, c, 14, 0xc33707d6, 9); + R(f2, c, d, a, b, 3, 0xf4d50d87, 14); + R(f2, b, c, d, a, 8, 0x455a14ed, 20); + R(f2, a, b, c, d, 13, 0xa9e3e905, 5); + R(f2, d, a, b, c, 2, 0xfcefa3f8, 9); + R(f2, c, d, a, b, 7, 0x676f02d9, 14); + R(f2, b, c, d, a, 12, 0x8d2a4c8a, 20); + + R(f3, a, b, c, d, 5, 0xfffa3942, 4); + R(f3, d, a, b, c, 8, 0x8771f681, 11); + R(f3, c, d, a, b, 11, 0x6d9d6122, 16); + R(f3, b, c, d, a, 14, 0xfde5380c, 23); + R(f3, a, b, c, d, 1, 0xa4beea44, 4); + R(f3, d, a, b, c, 4, 0x4bdecfa9, 11); + R(f3, c, d, a, b, 7, 0xf6bb4b60, 16); + R(f3, b, c, d, a, 10, 0xbebfbc70, 23); + R(f3, a, b, c, d, 13, 0x289b7ec6, 4); + R(f3, d, a, b, c, 0, 0xeaa127fa, 11); + R(f3, c, d, a, b, 3, 0xd4ef3085, 16); + R(f3, b, c, d, a, 6, 0x04881d05, 23); + R(f3, a, b, c, d, 9, 0xd9d4d039, 4); + R(f3, d, a, b, c, 12, 0xe6db99e5, 11); + R(f3, c, d, a, b, 15, 0x1fa27cf8, 16); + R(f3, b, c, d, a, 2, 0xc4ac5665, 23); + + R(f4, a, b, c, d, 0, 0xf4292244, 6); + R(f4, d, a, b, c, 7, 0x432aff97, 10); + R(f4, c, d, a, b, 14, 0xab9423a7, 15); + R(f4, b, c, d, a, 5, 0xfc93a039, 21); + R(f4, a, b, c, d, 12, 0x655b59c3, 6); + R(f4, d, a, b, c, 3, 0x8f0ccc92, 10); + R(f4, c, d, a, b, 10, 0xffeff47d, 15); + R(f4, b, c, d, a, 1, 0x85845dd1, 21); + R(f4, a, b, c, d, 8, 0x6fa87e4f, 6); + R(f4, d, a, b, c, 15, 0xfe2ce6e0, 10); + R(f4, c, d, a, b, 6, 0xa3014314, 15); + R(f4, b, c, d, a, 13, 0x4e0811a1, 21); + R(f4, a, b, c, d, 4, 0xf7537e82, 6); + R(f4, d, a, b, c, 11, 0xbd3af235, 10); + R(f4, c, d, a, b, 2, 0x2ad7d2bb, 15); + R(f4, b, c, d, a, 9, 0xeb86d391, 21); + + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; +} + +static void +md5_do_chunk(struct md5_ctx *ctx, const uint8_t buf[]) +{ + if (ptr_uint32_aligned(buf)) { /* aligned buf */ +#if WORDS_BIGENDIAN + uint32_t w[16]; cpu_to_le32_array(w, (const uint32_t *)buf, 16); +#else + const uint32_t *w = (const uint32_t *)buf; +#endif + md5_do_chunk_aligned(ctx, w); + } else { /* unaligned buf */ + uint32_t w[16]; memcpy(w, buf, 64); +#if WORDS_BIGENDIAN + cpu_to_le32_array(w, w, 16); +#endif + md5_do_chunk_aligned(ctx, w); + } +} + +static inline void +hs_cryptohash_md5_update(struct md5_ctx *ctx, const uint8_t *data, size_t len) +{ + size_t index = ctx->sz & 0x3f; + const size_t to_fill = 64 - index; + + ctx->sz += len; + + /* process partial buffer if there's enough data to make a block */ + if (index && len >= to_fill) { + memcpy(ctx->buf + index, data, to_fill); + md5_do_chunk(ctx, ctx->buf); + /* memset(ctx->buf, 0, 64); */ + len -= to_fill; + data += to_fill; + index = 0; + } + + /* process as many 64-blocks as possible */ + while (len >= 64) { + md5_do_chunk(ctx, data); + len -= 64; + data += 64; + } + + /* append data into buf */ + if (len) + memcpy(ctx->buf + index, data, len); +} + +static inline uint64_t +hs_cryptohash_md5_finalize(struct md5_ctx *ctx, uint8_t *out) +{ + static const uint8_t padding[64] = { 0x80, }; + const uint64_t sz = ctx->sz; + + /* add padding and update data with it */ + const uint64_t bits = cpu_to_le64(ctx->sz << 3); + + /* pad out to 56 */ + const size_t index = (ctx->sz & 0x3f); + const size_t padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); + hs_cryptohash_md5_update(ctx, padding, padlen); + + /* append length */ + hs_cryptohash_md5_update(ctx, (const uint8_t *) &bits, sizeof(bits)); + + /* output hash */ + cpu_to_le32_array((uint32_t *) out, ctx->h, 4); + + return sz; +} + +static inline void +hs_cryptohash_md5_hash (const uint8_t *data, size_t len, uint8_t *out) +{ + struct md5_ctx ctx; + + hs_cryptohash_md5_init(&ctx); + + hs_cryptohash_md5_update(&ctx, data, len); + + hs_cryptohash_md5_finalize(&ctx, out); +} #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptohash-md5-0.11.100.1/changelog.md new/cryptohash-md5-0.11.101.0/changelog.md --- old/cryptohash-md5-0.11.100.1/changelog.md 2016-06-28 09:14:08.000000000 +0200 +++ new/cryptohash-md5-0.11.101.0/changelog.md 2001-09-09 03:46:40.000000000 +0200 @@ -1,3 +1,18 @@ +## 0.11.101.0 + + - Add `Eq` instance for `Ctx` + - Add `start` and `startlazy` producing `Ctx` + - Remove ineffective RULES + - Declare `Crypto.Hash.MD5` module `-XTrustworthy` + - Convert to `CApiFFI` + - Added `...AndLength` variants of hashing functions: + + - `finalizeAndLength` + - `hashlazyAndLength` + - `hmaclazyAndLength` + + - Minor optimizations in `hmac` and `hash` + ## 0.11.100.1 - Use `__builtin_bswap{32,64}` only with GCC >= 4.3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptohash-md5-0.11.100.1/cryptohash-md5.cabal new/cryptohash-md5-0.11.101.0/cryptohash-md5.cabal --- old/cryptohash-md5-0.11.100.1/cryptohash-md5.cabal 2016-06-28 09:14:08.000000000 +0200 +++ new/cryptohash-md5-0.11.101.0/cryptohash-md5.cabal 2001-09-09 03:46:40.000000000 +0200 @@ -1,5 +1,5 @@ name: cryptohash-md5 -version: 0.11.100.1 +version: 0.11.101.0 description: A practical incremental and one-pass, pure API to the <https://en.wikipedia.org/wiki/MD5 MD5 hash algorithm> @@ -30,7 +30,14 @@ , GHC == 7.6.3 , GHC == 7.8.4 , GHC == 7.10.3 - , GHC == 8.0.1 + , GHC == 8.0.2 + , GHC == 8.2.2 + , GHC == 8.4.4 + , GHC == 8.6.5 + , GHC == 8.8.4 + , GHC == 8.10.4 + , GHC == 9.0.1 + , GHC == 9.2.0.20210821 extra-source-files: cbits/md5.h changelog.md @@ -41,14 +48,14 @@ library default-language: Haskell2010 - build-depends: base >= 4.5 && < 4.10 - , bytestring >= 0.9.2 && < 0.11 + build-depends: base >= 4.5 && < 4.17 + , bytestring >= 0.9.2 && < 0.12 hs-source-dirs: src exposed-modules: Crypto.Hash.MD5 + other-modules: Crypto.Hash.MD5.FFI Compat ghc-options: -Wall -fno-cse -O2 - cc-options: -Wall -O3 - c-sources: cbits/md5.c + cc-options: -Wall include-dirs: cbits test-suite test-md5 @@ -62,11 +69,11 @@ , base , bytestring - , base16-bytestring >= 0.1.1 && < 0.2 + , base16-bytestring >= 1.0.1.0 && < 1.1 , pureMD5 >= 2.1.3 && < 2.2 - , tasty == 0.11.* - , tasty-quickcheck == 0.8.* - , tasty-hunit == 0.9.* + , tasty >= 1.4 && <1.5 + , tasty-quickcheck == 0.10.* + , tasty-hunit == 0.10.* benchmark bench-md5 default-language: Haskell2010 @@ -76,4 +83,4 @@ build-depends: cryptohash-md5 , base , bytestring - , criterion == 1.1.* + , criterion == 1.5.* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptohash-md5-0.11.100.1/src/Compat.hs new/cryptohash-md5-0.11.101.0/src/Compat.hs --- old/cryptohash-md5-0.11.100.1/src/Compat.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/cryptohash-md5-0.11.101.0/src/Compat.hs 2001-09-09 03:46:40.000000000 +0200 @@ -0,0 +1,24 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE Trustworthy #-} + +-- | +-- Module : Compat +-- License : BSD-3 +-- Maintainer : Herbert Valerio Riedel <[email protected]> +-- Stability : stable +-- +-- Compat layer to reduce code exposure to CPP to a bare minimum +-- +module Compat (constructBS) where + +import Foreign.ForeignPtr (ForeignPtr) +import Data.Word (Word8) +import Data.ByteString.Internal (ByteString (..)) + +-- | Directly construct a 'ByteString', unsafely +constructBS :: ForeignPtr Word8 -> Int -> ByteString +#if MIN_VERSION_bytestring(0,11,0) +constructBS = BS +#else +constructBS = \fp -> PS fp 0 +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptohash-md5-0.11.100.1/src/Crypto/Hash/MD5/FFI.hs new/cryptohash-md5-0.11.101.0/src/Crypto/Hash/MD5/FFI.hs --- old/cryptohash-md5-0.11.100.1/src/Crypto/Hash/MD5/FFI.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/cryptohash-md5-0.11.101.0/src/Crypto/Hash/MD5/FFI.hs 2001-09-09 03:46:40.000000000 +0200 @@ -0,0 +1,61 @@ +{-# LANGUAGE CApiFFI #-} +{-# LANGUAGE Unsafe #-} + +-- Ugly hack to workaround https://ghc.haskell.org/trac/ghc/ticket/14452 +{-# OPTIONS_GHC -O0 + -fdo-lambda-eta-expansion + -fcase-merge + -fstrictness + -fno-omit-interface-pragmas + -fno-ignore-interface-pragmas #-} + +{-# OPTIONS_GHC -optc-Wall -optc-O3 #-} + +-- | +-- Module : Crypto.Hash.MD5.FFI +-- License : BSD-3 +-- +module Crypto.Hash.MD5.FFI where + +import Data.ByteString (ByteString) +import Data.Word +import Foreign.C.Types +import Foreign.Ptr + +-- | MD5 Context +-- +-- The context data is exactly 88 bytes long, however +-- the data in the context is stored in host-endianness. +-- +-- The context data is made up of +-- +-- * a 'Word64' representing the number of bytes already feed to hash algorithm so far, +-- +-- * a 64-element 'Word8' buffer holding partial input-chunks, and finally +-- +-- * a 4-element 'Word32' array holding the current work-in-progress digest-value. +-- +-- Consequently, a MD5 digest as produced by 'hash', 'hashlazy', or 'finalize' is 16 bytes long. +newtype Ctx = Ctx ByteString + deriving (Eq) + +foreign import capi unsafe "md5.h hs_cryptohash_md5_init" + c_md5_init :: Ptr Ctx -> IO () + +foreign import capi unsafe "md5.h hs_cryptohash_md5_update" + c_md5_update_unsafe :: Ptr Ctx -> Ptr Word8 -> CSize -> IO () + +foreign import capi safe "md5.h hs_cryptohash_md5_update" + c_md5_update_safe :: Ptr Ctx -> Ptr Word8 -> CSize -> IO () + +foreign import capi unsafe "md5.h hs_cryptohash_md5_finalize" + c_md5_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +foreign import capi unsafe "md5.h hs_cryptohash_md5_finalize" + c_md5_finalize_len :: Ptr Ctx -> Ptr Word8 -> IO Word64 + +foreign import capi unsafe "md5.h hs_cryptohash_md5_hash" + c_md5_hash_unsafe :: Ptr Word8 -> CSize -> Ptr Word8 -> IO () + +foreign import capi safe "md5.h hs_cryptohash_md5_hash" + c_md5_hash_safe :: Ptr Word8 -> CSize -> Ptr Word8 -> IO () diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptohash-md5-0.11.100.1/src/Crypto/Hash/MD5.hs new/cryptohash-md5-0.11.101.0/src/Crypto/Hash/MD5.hs --- old/cryptohash-md5-0.11.100.1/src/Crypto/Hash/MD5.hs 2016-06-28 09:14:08.000000000 +0200 +++ new/cryptohash-md5-0.11.101.0/src/Crypto/Hash/MD5.hs 2001-09-09 03:46:40.000000000 +0200 @@ -1,3 +1,4 @@ +{-# LANGUAGE Trustworthy #-} -- | -- Module : Crypto.Hash.MD5 -- License : BSD-style @@ -40,6 +41,9 @@ , update -- :: Ctx -> ByteString -> Ctx , updates -- :: Ctx -> [ByteString] -> Ctx , finalize -- :: Ctx -> ByteString + , finalizeAndLength -- :: Ctx -> (ByteString,Word64) + , start -- :: ByteString -> Ctx + , startlazy-- :: L.ByteString -> Ctx -- * Single Pass API -- @@ -49,6 +53,7 @@ -- -- - 'hash': create a digest ('init' + 'update' + 'finalize') from a strict 'ByteString' -- - 'hashlazy': create a digest ('init' + 'update' + 'finalize') from a lazy 'L.ByteString' + -- - 'hashlazyAndLength': create a digest ('init' + 'update' + 'finalizeAndLength') from a lazy 'L.ByteString' -- -- Example: -- @@ -64,6 +69,7 @@ , hash -- :: ByteString -> ByteString , hashlazy -- :: L.ByteString -> ByteString + , hashlazyAndLength -- :: L.ByteString -> (ByteString,Word64) -- ** HMAC-MD5 -- @@ -72,6 +78,7 @@ , hmac -- :: ByteString -> ByteString -> ByteString , hmaclazy -- :: ByteString -> L.ByteString -> ByteString + , hmaclazyAndLength -- :: ByteString -> L.ByteString -> (ByteString,Word64) ) where import Prelude hiding (init) @@ -83,11 +90,14 @@ import qualified Data.ByteString as B import Data.ByteString (ByteString) import Data.ByteString.Unsafe (unsafeUseAsCStringLen) -import Data.ByteString.Internal (create, toForeignPtr, memcpy) +import Data.ByteString.Internal (create, toForeignPtr, memcpy, mallocByteString) import Data.Bits (xor) import Data.Word import System.IO.Unsafe (unsafeDupablePerformIO) +import Compat (constructBS) +import Crypto.Hash.MD5.FFI + -- | perform IO for hashes that do allocation and ffi. -- unsafeDupablePerformIO is used when possible as the -- computation is pure and the output is directly linked @@ -96,22 +106,6 @@ unsafeDoIO :: IO a -> a unsafeDoIO = unsafeDupablePerformIO --- | MD5 Context --- --- The context data is exactly 88 bytes long, however --- the data in the context is stored in host-endianness. --- --- The context data is made up of --- --- * a 'Word64' representing the number of bytes already feed to hash algorithm so far, --- --- * a 64-element 'Word8' buffer holding partial input-chunks, and finally --- --- * a 4-element 'Word32' array holding the current work-in-progress digest-value. --- --- Consequently, a MD5 digest as produced by 'hash', 'hashlazy', or 'finalize' is 16 bytes long. -newtype Ctx = Ctx ByteString - -- keep this synchronised with cbits/md5.h {-# INLINE digestSize #-} digestSize :: Int @@ -121,18 +115,21 @@ sizeCtx :: Int sizeCtx = 88 -{-# RULES "digestSize" B.length (finalize init) = digestSize #-} -{-# RULES "hash" forall b. finalize (update init b) = hash b #-} -{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-} -{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-} -{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-} - {-# INLINE withByteStringPtr #-} withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a withByteStringPtr b f = withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) where (fptr, off, _) = toForeignPtr b +{-# INLINE create' #-} +-- | Variant of 'create' which allows to return an argument +create' :: Int -> (Ptr Word8 -> IO a) -> IO (ByteString,a) +create' l f = do + fp <- mallocByteString l + x <- withForeignPtr fp $ \p -> f p + let bs = constructBS fp l + return $! x `seq` bs `seq` (bs,x) + copyCtx :: Ptr Ctx -> Ptr Ctx -> IO () copyCtx dst src = memcpy (castPtr dst) (castPtr src) (fromIntegral sizeCtx) @@ -157,14 +154,7 @@ withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) -foreign import ccall unsafe "md5.h hs_cryptohash_md5_init" - c_md5_init :: Ptr Ctx -> IO () -foreign import ccall unsafe "md5.h hs_cryptohash_md5_update" - c_md5_update_unsafe :: Ptr Ctx -> Ptr Word8 -> CSize -> IO () - -foreign import ccall safe "md5.h hs_cryptohash_md5_update" - c_md5_update_safe :: Ptr Ctx -> Ptr Word8 -> CSize -> IO () -- 'safe' call overhead neglible for 16KiB and more c_md5_update :: Ptr Ctx -> Ptr Word8 -> CSize -> IO () @@ -172,8 +162,11 @@ | sz < 16384 = c_md5_update_unsafe pctx pbuf sz | otherwise = c_md5_update_safe pctx pbuf sz -foreign import ccall unsafe "md5.h hs_cryptohash_md5_finalize" - c_md5_finalize :: Ptr Ctx -> Ptr Word8 -> IO () +-- 'safe' call overhead neglible for 4KiB and more +c_md5_hash :: Ptr Word8 -> CSize -> Ptr Word8 -> IO () +c_md5_hash pbuf sz pout + | sz < 4096 = c_md5_hash_unsafe pbuf sz pout + | otherwise = c_md5_hash_safe pbuf sz pout updateInternalIO :: Ptr Ctx -> ByteString -> IO () updateInternalIO ptr d = @@ -182,6 +175,9 @@ finalizeInternalIO :: Ptr Ctx -> IO ByteString finalizeInternalIO ptr = create digestSize (c_md5_finalize ptr) +finalizeInternalIO' :: Ptr Ctx -> IO (ByteString,Word64) +finalizeInternalIO' ptr = create' digestSize (c_md5_finalize_len ptr) + {-# NOINLINE init #-} -- | create a new hash context init :: Ctx @@ -211,11 +207,28 @@ | validCtx ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO | otherwise = error "MD5.finalize: invalid Ctx" +{-# NOINLINE finalizeAndLength #-} +-- | Variant of 'finalize' also returning length of hashed content +-- +-- @since 0.11.101.0 +finalizeAndLength :: Ctx -> (ByteString,Word64) +finalizeAndLength ctx + | validCtx ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO' + | otherwise = error "SHA256.finalize: invalid Ctx" + {-# NOINLINE hash #-} -- | hash a strict bytestring into a digest bytestring (16 bytes) hash :: ByteString -> ByteString -hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do - c_md5_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr +-- hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do c_md5_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr +hash d = unsafeDoIO $ unsafeUseAsCStringLen d $ \(cs, len) -> create digestSize (c_md5_hash (castPtr cs) (fromIntegral len)) + +{-# NOINLINE start #-} +-- | hash a strict bytestring into a 'Ctx' +-- +-- @since 0.11.101.0 +start :: ByteString -> Ctx +start d = unsafeDoIO $ withCtxNew $ \ptr -> do + c_md5_init ptr >> updateInternalIO ptr d {-# NOINLINE hashlazy #-} -- | hash a lazy bytestring into a digest bytestring (16 bytes) @@ -223,6 +236,21 @@ hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do c_md5_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr +{-# NOINLINE hashlazyAndLength #-} +-- | Variant of 'hashlazy' which simultaneously computes the hash and length of a lazy bytestring. +-- +-- @since 0.11.101.0 +hashlazyAndLength :: L.ByteString -> (ByteString,Word64) +hashlazyAndLength l = unsafeDoIO $ withCtxNewThrow $ \ptr -> + c_md5_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO' ptr + +{-# NOINLINE startlazy #-} +-- | hash a lazy bytestring into a 'Ctx' +-- +-- @since 0.11.101.0 +startlazy :: L.ByteString -> Ctx +startlazy l = unsafeDoIO $ withCtxNew $ \ptr -> do + c_md5_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) {-# NOINLINE hmac #-} -- | Compute 16-byte <https://tools.ietf.org/html/rfc2104 RFC2104>-compatible @@ -257,4 +285,23 @@ k' = B.append kt pad kt = if B.length secret > 64 then hash secret else secret + pad = B.replicate (64 - B.length kt) 0 + +-- | Variant of 'hmaclazy' which also returns length of message +-- +-- @since 0.11.101.0 +hmaclazyAndLength :: ByteString -- ^ secret + -> L.ByteString -- ^ message + -> (ByteString,Word64) -- ^ digest (32 bytes) and length of message +hmaclazyAndLength secret msg = + (hash (B.append opad htmp), sz' - fromIntegral ipadLen) + where + (htmp, sz') = hashlazyAndLength (L.append ipad msg) + + opad = B.map (xor 0x5c) k' + ipad = L.fromChunks [B.map (xor 0x36) k'] + ipadLen = B.length k' + + k' = B.append kt pad + kt = if B.length secret > 64 then hash secret else secret pad = B.replicate (64 - B.length kt) 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptohash-md5-0.11.100.1/src-tests/test-md5.hs new/cryptohash-md5-0.11.101.0/src-tests/test-md5.hs --- old/cryptohash-md5-0.11.100.1/src-tests/test-md5.hs 2016-06-28 09:14:08.000000000 +0200 +++ new/cryptohash-md5-0.11.101.0/src-tests/test-md5.hs 2001-09-09 03:46:40.000000000 +0200 @@ -3,6 +3,7 @@ module Main (main) where import Data.Bits (xor) +import Data.Word (Word64) import Data.ByteString (ByteString) import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL @@ -46,11 +47,12 @@ katTests :: [TestTree] katTests - | length vectors == length answers = map makeTest (zip3 [1::Int ..] vectors answers) ++ [xltest] + | length vectors == length answers = map makeTest (zip3 [1::Int ..] vectors answers) ++ [xltest, xltest'] | otherwise = error "vectors/answers length mismatch" where makeTest (i, v, r) = testGroup ("vec"++show i) $ [ testCase "one-pass" (r @=? runTest v) + , testCase "one-pass'" (r @=? runTest' v) , testCase "inc-1" (r @=? runTestInc 1 v) , testCase "inc-2" (r @=? runTestInc 2 v) , testCase "inc-3" (r @=? runTestInc 3 v) @@ -65,25 +67,43 @@ , testCase "lazy-7" (r @=? runTestLazy 7 v) , testCase "lazy-8" (r @=? runTestLazy 8 v) , testCase "lazy-16" (r @=? runTestLazy 16 v) + , testCase "lazy-1'" (r @=? runTestLazy' 1 v) + , testCase "lazy-2'" (r @=? runTestLazy' 2 v) + , testCase "lazy-7'" (r @=? runTestLazy' 7 v) + , testCase "lazy-8'" (r @=? runTestLazy' 8 v) + , testCase "lazy-16'" (r @=? runTestLazy' 16 v) ] ++ [ testCase "lazy-63u" (r @=? runTestLazyU 63 v) | B.length v > 63 ] ++ [ testCase "lazy-65u" (r @=? runTestLazyU 65 v) | B.length v > 65 ] ++ [ testCase "lazy-97u" (r @=? runTestLazyU 97 v) | B.length v > 97 ] ++ - [ testCase "lazy-131u" (r @=? runTestLazyU 131 v) | B.length v > 131 ] + [ testCase "lazy-131u" (r @=? runTestLazyU 131 v) | B.length v > 131 ] ++ + [ testCase "lazy-63u'" (r @=? runTestLazyU' 63 v) | B.length v > 63 ] ++ + [ testCase "lazy-65u'" (r @=? runTestLazyU' 65 v) | B.length v > 65 ] ++ + [ testCase "lazy-97u'" (r @=? runTestLazyU' 97 v) | B.length v > 97 ] ++ + [ testCase "lazy-131u'" (r @=? runTestLazyU' 131 v) | B.length v > 131 ] runTest :: ByteString -> ByteString runTest = B16.encode . IUT.hash + runTest' :: ByteString -> ByteString + runTest' = B16.encode . IUT.finalize . IUT.start + runTestInc :: Int -> ByteString -> ByteString runTestInc i = B16.encode . IUT.finalize . myfoldl' IUT.update IUT.init . splitB i runTestLazy :: Int -> ByteString -> ByteString runTestLazy i = B16.encode . IUT.hashlazy . BL.fromChunks . splitB i + runTestLazy' :: Int -> ByteString -> ByteString + runTestLazy' i = B16.encode . IUT.finalize . IUT.startlazy . BL.fromChunks . splitB i + -- force unaligned md5-blocks runTestLazyU :: Int -> ByteString -> ByteString runTestLazyU i = B16.encode . IUT.hashlazy . BL.fromChunks . map B.copy . splitB i + runTestLazyU' :: Int -> ByteString -> ByteString + runTestLazyU' i = B16.encode . IUT.finalize . IUT.startlazy . BL.fromChunks . map B.copy . splitB i + ---- xltest = testGroup "XL-vec" @@ -91,6 +111,11 @@ where vecXL = BL.fromChunks (replicate 16777216 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno") + xltest' = testGroup "XL-vec'" + [ testCase "inc'" (ansXLTest @=? (B16.encode . IUT.finalize . IUT.startlazy) vecXL) ] + where + vecXL = BL.fromChunks (replicate 16777216 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno") + splitB :: Int -> ByteString -> [ByteString] splitB l b | B.length b > l = b1 : splitB l b2 @@ -110,7 +135,7 @@ , (rep 80 0xaa, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", x"6f630fad67cda0ee1fb1f562db3aa53e") ] where - x = fst.B16.decode + x = B16.decodeLenient rep n c = B.replicate n c rfc2202Tests :: [TestTree] @@ -125,7 +150,7 @@ hex = B16.encode --- define own 'foldl' here to avoid RULE rewriting to 'hashlazy' +-- define own 'foldl' here to avoid RULE rewriting to 'startlazy myfoldl' :: (b -> a -> b) -> b -> [a] -> b myfoldl' f z0 xs0 = lgo z0 xs0 where @@ -154,29 +179,48 @@ refImplTests :: [TestTree] refImplTests = [ testProperty "hash" prop_hash + , testProperty "start" prop_start , testProperty "hashlazy" prop_hashlazy + , testProperty "startlazy" prop_startlazy + , testProperty "hashlazyAndLength" prop_hashlazyAndLength , testProperty "hmac" prop_hmac , testProperty "hmaclazy" prop_hmaclazy + , testProperty "hmaclazyAndLength" prop_hmaclazyAndLength ] where prop_hash (RandBS bs) = ref_hash bs == IUT.hash bs + prop_start (RandBS bs) + = ref_hash bs == (IUT.finalize $ IUT.start bs) + prop_hashlazy (RandLBS bs) = ref_hashlazy bs == IUT.hashlazy bs + prop_hashlazyAndLength (RandLBS bs) + = ref_hashlazyAndLength bs == IUT.hashlazyAndLength bs + + prop_startlazy (RandLBS bs) + = ref_hashlazy bs == (IUT.finalize $ IUT.startlazy bs) + prop_hmac (RandBS k) (RandBS bs) = ref_hmac k bs == IUT.hmac k bs prop_hmaclazy (RandBS k) (RandLBS bs) = ref_hmaclazy k bs == IUT.hmaclazy k bs + prop_hmaclazyAndLength (RandBS k) (RandLBS bs) + = ref_hmaclazyAndLength k bs == IUT.hmaclazyAndLength k bs + ref_hash :: ByteString -> ByteString ref_hash = ref_hashlazy . fromStrict ref_hashlazy :: BL.ByteString -> ByteString ref_hashlazy = REF.md5DigestBytes . REF.md5 + ref_hashlazyAndLength :: BL.ByteString -> (ByteString,Word64) + ref_hashlazyAndLength x = (ref_hashlazy x, fromIntegral (BL.length x)) + -- stolen & adapted from SHA package ref_hmac :: ByteString -> ByteString -> ByteString ref_hmac k m = ref_hash (B.append opad (ref_hash (B.append ipad m))) @@ -195,6 +239,9 @@ ref_hmaclazy :: ByteString -> BL.ByteString -> ByteString ref_hmaclazy secret = ref_hmac secret . toStrict + ref_hmaclazyAndLength :: ByteString -> BL.ByteString -> (ByteString,Word64) + ref_hmaclazyAndLength secret msg = (ref_hmaclazy secret msg, fromIntegral (BL.length msg)) + -- toStrict/fromStrict only available with bytestring-0.10 and later toStrict = B.concat . BL.toChunks fromStrict = BL.fromChunks . (:[])
