11 #include <openssl/hmac.h>
12 #include <openssl/md5.h>
13 #include <openssl/ripemd.h>
14 #include <openssl/sha.h>
22 #include "KeccakHash.h"
27 #ifdef CVMFS_NAMESPACE_GUARD
28 namespace CVMFS_NAMESPACE_GUARD {
34 {
"",
"",
"-rmd160",
"-shake128",
""};
37 bool HexPtr::IsValid()
const {
38 const unsigned l = str->length();
41 const char *c = str->data();
44 for ( ; i < l; ++i, ++c) {
47 if ((*c <
'0') || (*c >
'f') || ((*c >
'9') && (*c <
'a')))
52 for (
unsigned j = 0; j <
kAny; ++j) {
55 if (i == hex_length) {
57 for ( ; (i < l) && (i-hex_length < algo_id_length); ++i, ++c) {
61 if ((i == l) && (l == hex_length + algo_id_length))
73 if (algorithm_option ==
"sha1")
75 if (algorithm_option ==
"rmd160")
77 if (algorithm_option ==
"shake128")
86 const unsigned length = hex.
str->length();
88 result =
Any(kMd5, hex);
90 result =
Any(kSha1, hex);
93 result =
Any(kRmd160, hex);
95 result =
Any(kShake128, hex);
108 const unsigned length = hex.
str->length();
113 result =
Any(kMd5, hex, suffix);
120 result =
Any(kSha1, hex, suffix);
127 ? *(hex.
str->rbegin())
129 result =
Any(kRmd160, hex, suffix);
136 ? *(hex.
str->rbegin())
138 result =
Any(kShake128, hex, suffix);
151 return sizeof(MD5_CTX);
153 return sizeof(SHA_CTX);
155 return sizeof(RIPEMD160_CTX);
157 return sizeof(Keccak_HashInstance);
160 "tried to generate hash context for unspecified hash. Aborting...");
165 HashReturn keccak_result;
169 MD5_Init(reinterpret_cast<MD5_CTX *>(context.
buffer));
173 SHA1_Init(reinterpret_cast<SHA_CTX *>(context.
buffer));
176 assert(context.
size ==
sizeof(RIPEMD160_CTX));
177 RIPEMD160_Init(reinterpret_cast<RIPEMD160_CTX *>(context.
buffer));
180 assert(context.
size ==
sizeof(Keccak_HashInstance));
181 keccak_result = Keccak_HashInitialize_SHAKE128(
182 reinterpret_cast<Keccak_HashInstance *>(context.
buffer));
183 assert(keccak_result == SUCCESS);
190 void Update(
const unsigned char *buffer,
const unsigned buffer_length,
193 HashReturn keccak_result;
197 MD5_Update(reinterpret_cast<MD5_CTX *>(context.
buffer),
198 buffer, buffer_length);
202 SHA1_Update(reinterpret_cast<SHA_CTX *>(context.
buffer),
203 buffer, buffer_length);
206 assert(context.
size ==
sizeof(RIPEMD160_CTX));
207 RIPEMD160_Update(reinterpret_cast<RIPEMD160_CTX *>(context.
buffer),
208 buffer, buffer_length);
211 assert(context.
size ==
sizeof(Keccak_HashInstance));
212 keccak_result = Keccak_HashUpdate(reinterpret_cast<Keccak_HashInstance *>(
213 context.
buffer), buffer, buffer_length * 8);
214 assert(keccak_result == SUCCESS);
222 HashReturn keccak_result;
226 MD5_Final(any_digest->
digest,
227 reinterpret_cast<MD5_CTX *>(context.
buffer));
231 SHA1_Final(any_digest->
digest,
232 reinterpret_cast<SHA_CTX *>(context.
buffer));
235 assert(context.
size ==
sizeof(RIPEMD160_CTX));
236 RIPEMD160_Final(any_digest->
digest,
237 reinterpret_cast<RIPEMD160_CTX *>(context.
buffer));
240 assert(context.
size ==
sizeof(Keccak_HashInstance));
241 keccak_result = Keccak_HashFinal(reinterpret_cast<Keccak_HashInstance *>(
243 assert(keccak_result == SUCCESS);
245 Keccak_HashSqueeze(reinterpret_cast<Keccak_HashInstance *>(
255 void HashMem(
const unsigned char *buffer,
const unsigned buffer_size,
263 Update(buffer, buffer_size, context);
264 Final(context, any_digest);
269 HashMem(reinterpret_cast<const unsigned char *>(content.data()),
270 content.length(), any_digest);
276 const unsigned char *buffer,
277 const unsigned buffer_size,
284 unsigned char key_block[block_size];
285 memset(key_block, 0, block_size);
286 if (key.length() > block_size) {
287 Any hash_key(algorithm);
288 HashMem(reinterpret_cast<const unsigned char *>(key.data()),
289 key.length(), &hash_key);
292 if (key.length() > 0)
293 memcpy(key_block, key.data(), key.length());
296 unsigned char pad_block[block_size];
298 Any hash_inner(algorithm);
300 context_inner.
buffer = alloca(context_inner.
size);
302 for (
unsigned i = 0; i < block_size; ++i)
303 pad_block[i] = key_block[i] ^ 0x36;
304 Update(pad_block, block_size, context_inner);
305 Update(buffer, buffer_size, context_inner);
306 Final(context_inner, &hash_inner);
310 context_outer.
buffer = alloca(context_outer.
size);
312 for (
unsigned i = 0; i < block_size; ++i)
313 pad_block[i] = key_block[i] ^ 0x5c;
314 Update(pad_block, block_size, context_outer);
317 Final(context_outer, any_digest);
327 unsigned char io_buffer[4096];
329 while ((actual_bytes = read(fd, io_buffer, 4096)) != 0) {
330 if (actual_bytes == -1) {
335 Update(io_buffer, actual_bytes, context);
337 Final(context, any_digest);
343 int fd = open(filename.c_str(), O_RDONLY);
347 bool result =
HashFd(fd, any_digest);
358 const string *str = ascii.
str;
361 MD5_Init(&md5_state);
362 MD5_Update(&md5_state, reinterpret_cast<const unsigned char *>(&(*str)[0]),
364 MD5_Final(
digest, &md5_state);
368 Md5::Md5(
const char *chars,
const unsigned length) {
372 MD5_Init(&md5_state);
373 MD5_Update(&md5_state, reinterpret_cast<const unsigned char *>(chars),
375 MD5_Final(
digest, &md5_state);
379 Md5::Md5(
const uint64_t lo,
const uint64_t hi) {
385 void Md5::ToIntPair(uint64_t *lo, uint64_t *hi)
const {
398 #ifndef OPENSSL_API_INTERFACE_V09
401 result.reserve(2 * SHA256_DIGEST_LENGTH);
402 for (
unsigned i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
403 const char d1 =
digest[i] / 16;
404 const char d2 =
digest[i] % 16;
405 result.push_back(d1 + ((d1 <= 9) ?
'0' :
'a' - 10));
406 result.push_back(d2 + ((d2 <= 9) ?
'0' :
'a' - 10));
413 #ifdef OPENSSL_API_INTERFACE_V09
416 int fd = open(filename.c_str(), O_RDONLY);
423 unsigned char io_buffer[4096];
425 while ((actual_bytes = read(fd, io_buffer, 4096)) != 0) {
426 if (actual_bytes == -1) {
432 SHA256_Update(&ctx, io_buffer, actual_bytes);
436 unsigned char digest[SHA256_DIGEST_LENGTH];
437 SHA256_Final(digest, &ctx);
442 string Sha256Mem(
const unsigned char *buffer,
const unsigned buffer_size) {
443 #ifdef OPENSSL_API_INTERFACE_V09
446 unsigned char digest[SHA256_DIGEST_LENGTH];
447 SHA256(buffer, buffer_size, digest);
453 return Sha256Mem(reinterpret_cast<const unsigned char *>(content.data()),
459 const std::string &key,
460 const std::string &content,
463 #ifdef OPENSSL_API_INTERFACE_V09
466 unsigned char digest[SHA256_DIGEST_LENGTH];
467 const unsigned block_size = 64;
468 const unsigned key_length = key.length();
469 unsigned char key_block[block_size];
470 memset(key_block, 0, block_size);
471 if (key_length > block_size) {
472 SHA256(reinterpret_cast<const unsigned char *>(key.data()), key_length,
475 if (key.length() > 0)
476 memcpy(key_block, key.data(), key_length);
479 unsigned char pad_block[block_size];
481 SHA256_CTX ctx_inner;
482 unsigned char digest_inner[SHA256_DIGEST_LENGTH];
483 SHA256_Init(&ctx_inner);
484 for (
unsigned i = 0; i < block_size; ++i)
485 pad_block[i] = key_block[i] ^ 0x36;
486 SHA256_Update(&ctx_inner, pad_block, block_size);
487 SHA256_Update(&ctx_inner, content.data(), content.length());
488 SHA256_Final(digest_inner, &ctx_inner);
491 SHA256_CTX ctx_outer;
492 SHA256_Init(&ctx_outer);
493 for (
unsigned i = 0; i < block_size; ++i)
494 pad_block[i] = key_block[i] ^ 0x5c;
495 SHA256_Update(&ctx_outer, pad_block, block_size);
496 SHA256_Update(&ctx_outer, digest_inner, SHA256_DIGEST_LENGTH);
498 SHA256_Final(digest, &ctx_outer);
500 return string(reinterpret_cast<const char *>(digest), SHA256_DIGEST_LENGTH);
507 #ifdef CVMFS_NAMESPACE_GUARD
void HashString(const std::string &content, Any *any_digest)
struct cvmcache_context * ctx
bool HashFile(const std::string &filename, Any *any_digest)
string Sha256String(const string &content)
const unsigned kAlgorithmIdSizes[]
void Hmac(const string &key, const unsigned char *buffer, const unsigned buffer_size, Any *any_digest)
assert((mem||(size==0))&&"Out Of Memory")
string Sha256File(const string &filename)
static string HexFromSha256(unsigned char digest[SHA256_DIGEST_LENGTH])
unsigned char digest[digest_size_]
const unsigned kBlockSizes[]
const unsigned kDigestSizes[]
string Sha256Mem(const unsigned char *buffer, const unsigned buffer_size)
static int Init(const loader::LoaderExports *loader_exports)
void Final(ContextPtr context, Any *any_digest)
const char * kAlgorithmIds[]
void HashMem(const unsigned char *buffer, const unsigned buffer_size, Any *any_digest)
unsigned GetContextSize(const Algorithms algorithm)
void Update(const unsigned char *buffer, const unsigned buffer_length, ContextPtr context)
Any MkFromSuffixedHexPtr(const HexPtr hex)
Algorithms ParseHashAlgorithm(const string &algorithm_option)
bool HashFd(int fd, Any *any_digest)
Any MkFromHexPtr(const HexPtr hex, const char suffix)
std::string Hmac256(const std::string &key, const std::string &content, bool raw_output)