11 #include <openssl/hmac.h>
12 #include <openssl/md5.h>
13 #include <openssl/ripemd.h>
14 #include <openssl/sha.h>
20 #include "KeccakHash.h"
27 #ifdef CVMFS_NAMESPACE_GUARD
28 namespace CVMFS_NAMESPACE_GUARD {
36 bool HexPtr::IsValid()
const {
37 const unsigned l = str->length();
40 const char *c = str->data();
43 for (; i < l; ++i, ++c) {
46 if ((*c <
'0') || (*c >
'f') || ((*c >
'9') && (*c <
'a')))
51 for (
unsigned j = 0; j <
kAny; ++j) {
54 if (i == hex_length) {
56 for (; (i < l) && (i - hex_length < algo_id_length); ++i, ++c) {
60 if ((i == l) && (l == hex_length + algo_id_length))
72 if (algorithm_option ==
"sha1")
74 if (algorithm_option ==
"rmd160")
76 if (algorithm_option ==
"shake128")
85 const unsigned length = hex.
str->length();
87 result =
Any(kMd5, hex);
89 result =
Any(kSha1, hex);
92 result =
Any(kRmd160, hex);
94 result =
Any(kShake128, hex);
107 const unsigned length = hex.
str->length();
111 ? *(hex.
str->rbegin())
113 result =
Any(kMd5, hex, suffix);
118 ? *(hex.
str->rbegin())
120 result =
Any(kSha1, hex, suffix);
128 ? *(hex.
str->rbegin())
130 result =
Any(kRmd160, hex, suffix);
138 ? *(hex.
str->rbegin())
140 result =
Any(kShake128, hex, suffix);
153 return sizeof(MD5_CTX);
155 return sizeof(SHA_CTX);
157 return sizeof(RIPEMD160_CTX);
159 return sizeof(Keccak_HashInstance);
162 "tried to generate hash context for unspecified hash. Aborting...");
167 HashReturn keccak_result;
171 MD5_Init(reinterpret_cast<MD5_CTX *>(context.
buffer));
175 SHA1_Init(reinterpret_cast<SHA_CTX *>(context.
buffer));
178 assert(context.
size ==
sizeof(RIPEMD160_CTX));
179 RIPEMD160_Init(reinterpret_cast<RIPEMD160_CTX *>(context.
buffer));
182 assert(context.
size ==
sizeof(Keccak_HashInstance));
183 keccak_result = Keccak_HashInitialize_SHAKE128(
184 reinterpret_cast<Keccak_HashInstance *>(context.
buffer));
185 assert(keccak_result == SUCCESS);
192 void Update(
const unsigned char *buffer,
const unsigned buffer_length,
194 HashReturn keccak_result;
198 MD5_Update(reinterpret_cast<MD5_CTX *>(context.
buffer), buffer,
203 SHA1_Update(reinterpret_cast<SHA_CTX *>(context.
buffer), buffer,
207 assert(context.
size ==
sizeof(RIPEMD160_CTX));
208 RIPEMD160_Update(reinterpret_cast<RIPEMD160_CTX *>(context.
buffer),
209 buffer, buffer_length);
212 assert(context.
size ==
sizeof(Keccak_HashInstance));
213 keccak_result = Keccak_HashUpdate(
214 reinterpret_cast<Keccak_HashInstance *>(context.
buffer), buffer,
216 assert(keccak_result == SUCCESS);
224 HashReturn keccak_result;
228 MD5_Final(any_digest->
digest,
229 reinterpret_cast<MD5_CTX *>(context.
buffer));
233 SHA1_Final(any_digest->
digest,
234 reinterpret_cast<SHA_CTX *>(context.
buffer));
237 assert(context.
size ==
sizeof(RIPEMD160_CTX));
238 RIPEMD160_Final(any_digest->
digest,
239 reinterpret_cast<RIPEMD160_CTX *>(context.
buffer));
242 assert(context.
size ==
sizeof(Keccak_HashInstance));
243 keccak_result = Keccak_HashFinal(
244 reinterpret_cast<Keccak_HashInstance *>(context.
buffer), NULL);
245 assert(keccak_result == SUCCESS);
246 keccak_result = Keccak_HashSqueeze(
247 reinterpret_cast<Keccak_HashInstance *>(context.
buffer),
257 void HashMem(
const unsigned char *buffer,
const unsigned buffer_size,
264 Update(buffer, buffer_size, context);
265 Final(context, any_digest);
270 HashMem(reinterpret_cast<const unsigned char *>(content.data()),
271 content.length(), any_digest);
276 const unsigned char *buffer,
277 const unsigned buffer_size,
283 unsigned char key_block[block_size];
284 memset(key_block, 0, block_size);
285 if (key.length() > block_size) {
286 Any hash_key(algorithm);
287 HashMem(reinterpret_cast<const unsigned char *>(key.data()), key.length(),
291 if (key.length() > 0)
292 memcpy(key_block, key.data(), key.length());
295 unsigned char pad_block[block_size];
297 Any hash_inner(algorithm);
299 context_inner.
buffer = alloca(context_inner.
size);
301 for (
unsigned i = 0; i < block_size; ++i)
302 pad_block[i] = key_block[i] ^ 0x36;
303 Update(pad_block, block_size, context_inner);
304 Update(buffer, buffer_size, context_inner);
305 Final(context_inner, &hash_inner);
309 context_outer.
buffer = alloca(context_outer.
size);
311 for (
unsigned i = 0; i < block_size; ++i)
312 pad_block[i] = key_block[i] ^ 0x5c;
313 Update(pad_block, block_size, context_outer);
316 Final(context_outer, any_digest);
326 unsigned char io_buffer[4096];
328 while ((actual_bytes = read(fd, io_buffer, 4096)) != 0) {
329 if (actual_bytes == -1) {
334 Update(io_buffer, actual_bytes, context);
336 Final(context, any_digest);
342 int fd = open(filename.c_str(), O_RDONLY);
346 bool result =
HashFd(fd, any_digest);
357 const string *str = ascii.
str;
360 MD5_Init(&md5_state);
361 MD5_Update(&md5_state, reinterpret_cast<const unsigned char *>(&(*str)[0]),
363 MD5_Final(
digest, &md5_state);
367 Md5::Md5(
const char *chars,
const unsigned length) {
371 MD5_Init(&md5_state);
372 MD5_Update(&md5_state, reinterpret_cast<const unsigned char *>(chars),
374 MD5_Final(
digest, &md5_state);
378 Md5::Md5(
const uint64_t lo,
const uint64_t hi) {
381 memcpy(
digest + 8, &hi, 8);
384 void Md5::ToIntPair(uint64_t *lo, uint64_t *hi)
const {
386 memcpy(hi,
digest + 8, 8);
397 #ifndef OPENSSL_API_INTERFACE_V09
400 result.reserve(2 * SHA256_DIGEST_LENGTH);
401 for (
unsigned i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
402 const char d1 =
digest[i] / 16;
403 const char d2 =
digest[i] % 16;
404 result.push_back(d1 + ((d1 <= 9) ?
'0' :
'a' - 10));
405 result.push_back(d2 + ((d2 <= 9) ?
'0' :
'a' - 10));
412 #ifdef OPENSSL_API_INTERFACE_V09
415 int fd = open(filename.c_str(), O_RDONLY);
422 unsigned char io_buffer[4096];
424 while ((actual_bytes = read(fd, io_buffer, 4096)) != 0) {
425 if (actual_bytes == -1) {
431 SHA256_Update(&ctx, io_buffer, actual_bytes);
435 unsigned char digest[SHA256_DIGEST_LENGTH];
436 SHA256_Final(digest, &ctx);
441 string Sha256Mem(
const unsigned char *buffer,
const unsigned buffer_size) {
442 #ifdef OPENSSL_API_INTERFACE_V09
445 unsigned char digest[SHA256_DIGEST_LENGTH];
446 SHA256(buffer, buffer_size, digest);
452 return Sha256Mem(reinterpret_cast<const unsigned char *>(content.data()),
458 const std::string &content,
460 #ifdef OPENSSL_API_INTERFACE_V09
463 unsigned char digest[SHA256_DIGEST_LENGTH];
464 const unsigned block_size = 64;
465 const unsigned key_length = key.length();
466 unsigned char key_block[block_size];
467 memset(key_block, 0, block_size);
468 if (key_length > block_size) {
469 SHA256(reinterpret_cast<const unsigned char *>(key.data()), key_length,
472 if (key.length() > 0)
473 memcpy(key_block, key.data(), key_length);
476 unsigned char pad_block[block_size];
478 SHA256_CTX ctx_inner;
479 unsigned char digest_inner[SHA256_DIGEST_LENGTH];
480 SHA256_Init(&ctx_inner);
481 for (
unsigned i = 0; i < block_size; ++i)
482 pad_block[i] = key_block[i] ^ 0x36;
483 SHA256_Update(&ctx_inner, pad_block, block_size);
484 SHA256_Update(&ctx_inner, content.data(), content.length());
485 SHA256_Final(digest_inner, &ctx_inner);
488 SHA256_CTX ctx_outer;
489 SHA256_Init(&ctx_outer);
490 for (
unsigned i = 0; i < block_size; ++i)
491 pad_block[i] = key_block[i] ^ 0x5c;
492 SHA256_Update(&ctx_outer, pad_block, block_size);
493 SHA256_Update(&ctx_outer, digest_inner, SHA256_DIGEST_LENGTH);
495 SHA256_Final(digest, &ctx_outer);
497 return string(reinterpret_cast<const char *>(digest), SHA256_DIGEST_LENGTH);
504 #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)