From 38bdea4e069574c26751627039b67fc53d7b240c Mon Sep 17 00:00:00 2001 From: Nils Maier Date: Fri, 20 Sep 2013 22:39:33 +0200 Subject: [PATCH] Add internal md5 and sha1 message digests --- configure.ac | 6 +- src/InternalMessageDigestImpl.cc | 110 +++++++++++ src/Makefile.am | 4 + src/md5.c | 311 +++++++++++++++++++++++++++++++ src/md5.h | 47 +++++ src/sha1.c | 160 ++++++++++++++++ src/sha1.h | 28 +++ test/HttpResponseTest.cc | 6 + test/MessageDigestTest.cc | 8 + 9 files changed, 679 insertions(+), 1 deletion(-) create mode 100644 src/InternalMessageDigestImpl.cc create mode 100644 src/md5.c create mode 100644 src/md5.h create mode 100644 src/sha1.c create mode 100644 src/sha1.h diff --git a/configure.ac b/configure.ac index e888a112..ed37b6bb 100644 --- a/configure.ac +++ b/configure.ac @@ -453,6 +453,9 @@ else if test "x$have_openssl" = "xyes"; then AC_DEFINE([USE_OPENSSL_MD], [1], [What message digest implementation to use]) use_md="openssl" + else + AC_DEFINE([USE_INTERNAL_MD], [1], [What message digest implementation to use]) + use_md="internal" fi fi fi @@ -481,6 +484,7 @@ AM_CONDITIONAL([HAVE_LIBGCRYPT], [ test "x$have_libgcrypt" = "xyes" ]) AM_CONDITIONAL([USE_LIBGCRYPT_MD], [ test "x$use_md" = "xlibgcrypt"]) AM_CONDITIONAL([HAVE_OPENSSL], [ test "x$have_openssl" = "xyes" ]) AM_CONDITIONAL([USE_OPENSSL_MD], [ test "x$use_md" = "xopenssl"]) +AM_CONDITIONAL([USE_INTERNAL_MD], [ test "x$use_md" = "xinternal"]) if test "x$use_md" != "x"; then AC_DEFINE([ENABLE_MESSAGE_DIGEST], [1], @@ -969,7 +973,7 @@ echo "Epoll: $have_epoll" echo "Bittorrent: $enable_bittorrent" echo "Metalink: $enable_metalink" echo "XML-RPC: $enable_xml_rpc" -echo "Message Digest: $enable_message_digest" +echo "Message Digest: $use_md" echo "WebSocket: $enable_websocket" echo "Libaria2: $enable_libaria2" if test "x$enable_libaria2" = "xyes"; then diff --git a/src/InternalMessageDigestImpl.cc b/src/InternalMessageDigestImpl.cc new file mode 100644 index 00000000..d5aabc66 --- /dev/null +++ b/src/InternalMessageDigestImpl.cc @@ -0,0 +1,110 @@ +/* */ + +#include "MessageDigestImpl.h" + +#include "md5.h" +#include "sha1.h" + +namespace aria2 { +namespace { + +template +class MessageDigestBase : public MessageDigestImpl { +public: + MessageDigestBase() { reset(); } + virtual ~MessageDigestBase() { + free_fn(&ctx_); + } + + static size_t length() { + return dlen; + } + virtual size_t getDigestLength() const CXX11_OVERRIDE { + return dlen; + } + virtual void reset() CXX11_OVERRIDE { + printf("hash-%d\n", dlen); + init_fn(&ctx_); + } + virtual void update(const void* data, size_t length) CXX11_OVERRIDE { + auto bytes = reinterpret_cast(data); + while (length) { + size_t l = std::min(length, (size_t)std::numeric_limits::max()); + update_fn(ctx_, bytes, l); + length -= l; + bytes += l; + } + } + virtual void digest(unsigned char* md) CXX11_OVERRIDE { + final_fn(ctx_, md); + } +private: + ctx_t* ctx_; +}; + +typedef MessageDigestBase +MessageDigestMD5; +typedef MessageDigestBase +MessageDigestSHA1; + +} // namespace + +std::unique_ptr MessageDigestImpl::sha1() +{ + return std::unique_ptr(new MessageDigestSHA1()); +} + +MessageDigestImpl::hashes_t MessageDigestImpl::hashes = { + { "sha-1", make_hi() }, + { "md5", make_hi() }, +}; + +} // namespace aria2 diff --git a/src/Makefile.am b/src/Makefile.am index 15ac829a..a6efa20f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -333,6 +333,10 @@ if USE_WINDOWS_MD SRCS += WinMessageDigestImpl.cc endif # USE_WINDOWS_MD +if USE_INTERNAL_MD +SRCS += InternalMessageDigestImpl.cc sha1.c md5.c +endif # USE_WINDOWS_MD + if HAVE_LIBGNUTLS SRCS += LibgnutlsTLSContext.cc LibgnutlsTLSContext.h \ LibgnutlsTLSSession.cc LibgnutlsTLSSession.h diff --git a/src/md5.c b/src/md5.c new file mode 100644 index 00000000..117b696c --- /dev/null +++ b/src/md5.c @@ -0,0 +1,311 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#include "md5.h" + +#include +#include + +struct MD5_CTX { + size_t lo, hi; + size_t a, b, c, d; + uint8_t buffer[64]; + size_t block[16]; +}; + + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(size_t *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (size_t)ptr[(n) * 4] | \ + ((size_t)ptr[(n) * 4 + 1] << 8) | \ + ((size_t)ptr[(n) * 4 + 2] << 16) | \ + ((size_t)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +static const void *body(struct MD5_CTX *ctx, const void *data, size_t size) +{ + const uint8_t *ptr; + size_t a, b, c, d; + size_t saved_a, saved_b, saved_c, saved_d; + + ptr = data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23) + +/* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +int MD5_Init(struct MD5_CTX **ctx) +{ + *ctx = malloc(sizeof(struct MD5_CTX)); + if (!*ctx) { + return 0; + } + (*ctx)->a = 0x67452301; + (*ctx)->b = 0xefcdab89; + (*ctx)->c = 0x98badcfe; + (*ctx)->d = 0x10325476; + + (*ctx)->lo = 0; + (*ctx)->hi = 0; + return 1; +} + +void MD5_Update(struct MD5_CTX *ctx, const void *data, size_t size) +{ + size_t saved_lo; + size_t used, free; + + saved_lo = ctx->lo; + if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->hi++; + ctx->hi += size >> 29; + + used = saved_lo & 0x3f; + + if (used) { + free = 64 - used; + + if (size < free) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, free); + data = (unsigned char *)data + free; + size -= free; + body(ctx, ctx->buffer, 64); + } + + if (size >= 64) { + data = body(ctx, data, size & ~(size_t)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +void MD5_Final(struct MD5_CTX *ctx, unsigned char* result) +{ + size_t used, free; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + free = 64 - used; + + if (free < 8) { + memset(&ctx->buffer[used], 0, free); + body(ctx, ctx->buffer, 64); + used = 0; + free = 64; + } + + memset(&ctx->buffer[used], 0, free - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = ctx->lo; + ctx->buffer[57] = ctx->lo >> 8; + ctx->buffer[58] = ctx->lo >> 16; + ctx->buffer[59] = ctx->lo >> 24; + ctx->buffer[60] = ctx->hi; + ctx->buffer[61] = ctx->hi >> 8; + ctx->buffer[62] = ctx->hi >> 16; + ctx->buffer[63] = ctx->hi >> 24; + + body(ctx, ctx->buffer, 64); + + result[0] = ctx->a; + result[1] = ctx->a >> 8; + result[2] = ctx->a >> 16; + result[3] = ctx->a >> 24; + result[4] = ctx->b; + result[5] = ctx->b >> 8; + result[6] = ctx->b >> 16; + result[7] = ctx->b >> 24; + result[8] = ctx->c; + result[9] = ctx->c >> 8; + result[10] = ctx->c >> 16; + result[11] = ctx->c >> 24; + result[12] = ctx->d; + result[13] = ctx->d >> 8; + result[14] = ctx->d >> 16; + result[15] = ctx->d >> 24; +} + +void MD5_Free(struct MD5_CTX** ctx) { + if (!ctx || !*ctx) { + return; + } + free(*ctx); + *ctx = NULL; +} diff --git a/src/md5.h b/src/md5.h new file mode 100644 index 00000000..d8d475b0 --- /dev/null +++ b/src/md5.h @@ -0,0 +1,47 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * See md5.c for more information. + */ + +#ifndef INTERNAL_MD5_H +#define INTERNAL_MD5_H + +#include +#include + +struct MD5_CTX; + +#define MD5_LENGTH 16 + +#ifdef __cplusplus +extern "C" { +#endif +int MD5_Init(struct MD5_CTX **ctx); +void MD5_Update(struct MD5_CTX *ctx, const void *data, size_t size); +void MD5_Final(struct MD5_CTX *ctx, uint8_t *result); +void MD5_Free(struct MD5_CTX **ctx); +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* INTERNAL_MD5_H */ diff --git a/src/sha1.c b/src/sha1.c new file mode 100644 index 00000000..2d215ff6 --- /dev/null +++ b/src/sha1.c @@ -0,0 +1,160 @@ +/* This code is public-domain - it is based on libcrypt + * placed in the public domain by Wei Dai and other contributors. + */ + +#include "sha1.h" + +#include +#include +#include + +#define BLOCK_LENGTH 64 + +union _buffer { + uint8_t b[BLOCK_LENGTH]; + uint32_t w[BLOCK_LENGTH/4]; +}; + +union _state { + uint8_t b[SHA1_LENGTH]; + uint32_t w[SHA1_LENGTH/4]; +}; + +struct SHA1_CTX { + union _buffer buffer; + uint8_t bufferOffset; + union _state state; + uint32_t byteCount; + uint8_t keyBuffer[BLOCK_LENGTH]; + uint8_t innerHash[SHA1_LENGTH]; +}; + +#define SHA1_K0 0x5a827999 +#define SHA1_K20 0x6ed9eba1 +#define SHA1_K40 0x8f1bbcdc +#define SHA1_K60 0xca62c1d6 + +const uint8_t sha1InitState[] = { + 0x01,0x23,0x45,0x67, // H0 + 0x89,0xab,0xcd,0xef, // H1 + 0xfe,0xdc,0xba,0x98, // H2 + 0x76,0x54,0x32,0x10, // H3 + 0xf0,0xe1,0xd2,0xc3 // H4 +}; + +static uint32_t sha1_rol32(uint32_t number, uint8_t bits) { + return ((number << bits) | (number >> (32-bits))); +} + +static void sha1_hashBlock(struct SHA1_CTX *s) { + uint8_t i; + uint32_t a,b,c,d,e,t; + + a=s->state.w[0]; + b=s->state.w[1]; + c=s->state.w[2]; + d=s->state.w[3]; + e=s->state.w[4]; + for (i=0; i<80; i++) { + if (i>=16) { + t = s->buffer.w[(i+13)&15] ^ s->buffer.w[(i+8)&15] ^ s->buffer.w[(i+2)&15] ^ s->buffer.w[i&15]; + s->buffer.w[i&15] = sha1_rol32(t,1); + } + if (i<20) { + t = (d ^ (b & (c ^ d))) + SHA1_K0; + } else if (i<40) { + t = (b ^ c ^ d) + SHA1_K20; + } else if (i<60) { + t = ((b & c) | (d & (b | c))) + SHA1_K40; + } else { + t = (b ^ c ^ d) + SHA1_K60; + } + t+=sha1_rol32(a,5) + e + s->buffer.w[i&15]; + e=d; + d=c; + c=sha1_rol32(b,30); + b=a; + a=t; + } + s->state.w[0] += a; + s->state.w[1] += b; + s->state.w[2] += c; + s->state.w[3] += d; + s->state.w[4] += e; +} + +static void sha1_addUncounted(struct SHA1_CTX *s, uint8_t data) { + s->buffer.b[s->bufferOffset ^ 3] = data; + s->bufferOffset++; + if (s->bufferOffset == BLOCK_LENGTH) { + sha1_hashBlock(s); + s->bufferOffset = 0; + } +} + +static void sha1_writebyte(struct SHA1_CTX *s, uint8_t data) { + ++s->byteCount; + sha1_addUncounted(s, data); +} + +static void sha1_pad(struct SHA1_CTX *s) { + // Implement SHA-1 padding (fips180-2 ยง5.1.1) + + // Pad with 0x80 followed by 0x00 until the end of the block + sha1_addUncounted(s, 0x80); + while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); + + // Append length in the last 8 bytes + sha1_addUncounted(s, 0); // We're only using 32 bit lengths + sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths + sha1_addUncounted(s, 0); // So zero pad the top bits + sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 + sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as + sha1_addUncounted(s, s->byteCount >> 13); // byte. + sha1_addUncounted(s, s->byteCount >> 5); + sha1_addUncounted(s, s->byteCount << 3); +} + +int SHA1_Init(struct SHA1_CTX **s) { + *s = malloc(sizeof(struct SHA1_CTX)); + if (!*s) { + return 0; + } + memcpy((*s)->state.b, sha1InitState, SHA1_LENGTH); + (*s)->byteCount = 0; + (*s)->bufferOffset = 0; + return 1; +} + +void SHA1_Update(struct SHA1_CTX *s, const void *data, size_t len) { + const uint8_t *bytes = data; + for (;len--;) sha1_writebyte(s, *bytes++); +} + +void SHA1_Final(struct SHA1_CTX *s, unsigned char* result) { + int i; + // Pad to complete the last block + sha1_pad(s); + + // Swap byte order back + for (i=0; i<5; i++) { + uint32_t a,b; + a=s->state.w[i]; + b=a<<24; + b|=(a<<8) & 0x00ff0000; + b|=(a>>8) & 0x0000ff00; + b|=a>>24; + s->state.w[i]=b; + } + + // Return pointer to hash (20 characters) + memcpy(result, s->state.b, sizeof(s->state.b)); +} + +void SHA1_Free(struct SHA1_CTX** s) { + if (!s || !*s) { + return; + } + free(*s); + *s = NULL; +} diff --git a/src/sha1.h b/src/sha1.h new file mode 100644 index 00000000..2c246c47 --- /dev/null +++ b/src/sha1.h @@ -0,0 +1,28 @@ +/* This code is public-domain - it is based on libcrypt + * placed in the public domain by Wei Dai and other contributors. + */ + +#ifndef INTERNAL_SHA1_H +#define INTERNAL_SHA1_H + +#include +#include + +#define SHA1_LENGTH 20 + +struct SHA1_CTX; + +#ifdef __cplusplus +extern "C" { +#endif + +int SHA1_Init(struct SHA1_CTX **s); +void SHA1_Update(struct SHA1_CTX *s, const void *data, size_t len); +void SHA1_Final(struct SHA1_CTX *s, uint8_t *result); +void SHA1_Free(struct SHA1_CTX **s); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* INTERNAL_SHA1_H */ diff --git a/test/HttpResponseTest.cc b/test/HttpResponseTest.cc index 5ba12c84..6bec45db 100644 --- a/test/HttpResponseTest.cc +++ b/test/HttpResponseTest.cc @@ -654,14 +654,20 @@ void HttpResponseTest::testGetDigest() "MD5=LJDK2+9ClF8Nz/K5WZd/+A=="); std::vector result; httpResponse.getDigest(result); +#ifdef USE_INTERNAL_MD + CPPUNIT_ASSERT_EQUAL((size_t)2, result.size()); +#else CPPUNIT_ASSERT_EQUAL((size_t)3, result.size()); +#endif Checksum c = result[0]; +#ifndef USE_INTERNAL_MD CPPUNIT_ASSERT_EQUAL(std::string("sha-256"), c.getHashType()); CPPUNIT_ASSERT_EQUAL(std::string("f83f271ae773dc6fe4a6454a41e0eb237c43e7bbf451e426cc60993a4d379ec5"), util::toHex(c.getDigest())); c = result[1]; +#endif CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), c.getHashType()); CPPUNIT_ASSERT_EQUAL(std::string("f36003f22b462ffa184390533c500d8989e9f681"), util::toHex(c.getDigest())); diff --git a/test/MessageDigestTest.cc b/test/MessageDigestTest.cc index 04170a0c..28b81394 100644 --- a/test/MessageDigestTest.cc +++ b/test/MessageDigestTest.cc @@ -18,9 +18,11 @@ class MessageDigestTest:public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_END(); std::unique_ptr sha1_; + std::unique_ptr md5_; public: void setUp() { + md5_ = MessageDigest::create("md5"); sha1_ = MessageDigest::sha1(); } @@ -37,6 +39,10 @@ CPPUNIT_TEST_SUITE_REGISTRATION( MessageDigestTest ); void MessageDigestTest::testDigest() { + md5_->update("aria2", 5); + CPPUNIT_ASSERT_EQUAL(std::string("2c90cadbef42945f0dcff2b959977ff8"), + util::toHex(md5_->digest())); + sha1_->update("aria2", 5); CPPUNIT_ASSERT_EQUAL(std::string("f36003f22b462ffa184390533c500d8989e9f681"), util::toHex(sha1_->digest())); @@ -44,6 +50,7 @@ void MessageDigestTest::testDigest() void MessageDigestTest::testSupports() { + CPPUNIT_ASSERT(MessageDigest::supports("md5")); CPPUNIT_ASSERT(MessageDigest::supports("sha-1")); // Fails because sha1 is not valid name. CPPUNIT_ASSERT(!MessageDigest::supports("sha1")); @@ -51,6 +58,7 @@ void MessageDigestTest::testSupports() void MessageDigestTest::testGetDigestLength() { + CPPUNIT_ASSERT_EQUAL((size_t)16, MessageDigest::getDigestLength("md5")); CPPUNIT_ASSERT_EQUAL((size_t)20, MessageDigest::getDigestLength("sha-1")); CPPUNIT_ASSERT_EQUAL((size_t)20, sha1_->getDigestLength()); }