mirror of https://github.com/aria2/aria2
Add internal md5 and sha1 message digests
parent
a1deb0e9f1
commit
38bdea4e06
|
@ -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
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2013 Nils Maier
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
|
||||
#include "MessageDigestImpl.h"
|
||||
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
|
||||
namespace aria2 {
|
||||
namespace {
|
||||
|
||||
template<size_t dlen,
|
||||
typename ctx_t,
|
||||
int (*init_fn)(ctx_t**),
|
||||
void (*update_fn)(ctx_t*, const void*, size_t),
|
||||
void (*final_fn)(ctx_t*, uint8_t*),
|
||||
void (*free_fn)(ctx_t**)>
|
||||
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<const char*>(data);
|
||||
while (length) {
|
||||
size_t l = std::min(length, (size_t)std::numeric_limits<uint32_t>::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<MD5_LENGTH,
|
||||
struct MD5_CTX,
|
||||
MD5_Init,
|
||||
MD5_Update,
|
||||
MD5_Final,
|
||||
MD5_Free>
|
||||
MessageDigestMD5;
|
||||
typedef MessageDigestBase<SHA1_LENGTH,
|
||||
SHA1_CTX,
|
||||
SHA1_Init,
|
||||
SHA1_Update,
|
||||
SHA1_Final,
|
||||
SHA1_Free>
|
||||
MessageDigestSHA1;
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1()
|
||||
{
|
||||
return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA1());
|
||||
}
|
||||
|
||||
MessageDigestImpl::hashes_t MessageDigestImpl::hashes = {
|
||||
{ "sha-1", make_hi<MessageDigestSHA1>() },
|
||||
{ "md5", make_hi<MessageDigestMD5>() },
|
||||
};
|
||||
|
||||
} // namespace aria2
|
|
@ -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
|
||||
|
|
|
@ -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 <solar at openwall.com>
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
|
@ -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 <solar at openwall.com>
|
||||
*
|
||||
* 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 <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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 */
|
|
@ -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 <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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 <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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 */
|
|
@ -654,14 +654,20 @@ void HttpResponseTest::testGetDigest()
|
|||
"MD5=LJDK2+9ClF8Nz/K5WZd/+A==");
|
||||
std::vector<Checksum> 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()));
|
||||
|
|
|
@ -18,9 +18,11 @@ class MessageDigestTest:public CppUnit::TestFixture {
|
|||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
std::unique_ptr<MessageDigest> sha1_;
|
||||
std::unique_ptr<MessageDigest> 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());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue