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);
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,
192 HashReturn keccak_result;
196 MD5_Update(reinterpret_cast<MD5_CTX *>(context.
buffer), buffer,
201 SHA1_Update(reinterpret_cast<SHA_CTX *>(context.
buffer), buffer,
205 assert(context.
size ==
sizeof(RIPEMD160_CTX));
206 RIPEMD160_Update(reinterpret_cast<RIPEMD160_CTX *>(context.
buffer),
207 buffer, buffer_length);
210 assert(context.
size ==
sizeof(Keccak_HashInstance));
211 keccak_result = Keccak_HashUpdate(
212 reinterpret_cast<Keccak_HashInstance *>(context.
buffer), buffer,
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(
242 reinterpret_cast<Keccak_HashInstance *>(context.
buffer), NULL);
243 assert(keccak_result == SUCCESS);
244 keccak_result = Keccak_HashSqueeze(
245 reinterpret_cast<Keccak_HashInstance *>(context.
buffer),
255 void HashMem(
const unsigned char *buffer,
const unsigned buffer_size,
262 Update(buffer, buffer_size, context);
263 Final(context, any_digest);
268 HashMem(reinterpret_cast<const unsigned char *>(content.data()),
269 content.length(), any_digest);
274 const unsigned char *buffer,
275 const unsigned buffer_size,
281 unsigned char key_block[block_size];
282 memset(key_block, 0, block_size);
283 if (key.length() > block_size) {
284 Any hash_key(algorithm);
285 HashMem(reinterpret_cast<const unsigned char *>(key.data()), key.length(),
289 if (key.length() > 0)
290 memcpy(key_block, key.data(), key.length());
293 unsigned char pad_block[block_size];
295 Any hash_inner(algorithm);
297 context_inner.
buffer = alloca(context_inner.
size);
299 for (
unsigned i = 0; i < block_size; ++i)
300 pad_block[i] = key_block[i] ^ 0x36;
301 Update(pad_block, block_size, context_inner);
302 Update(buffer, buffer_size, context_inner);
303 Final(context_inner, &hash_inner);
307 context_outer.
buffer = alloca(context_outer.
size);
309 for (
unsigned i = 0; i < block_size; ++i)
310 pad_block[i] = key_block[i] ^ 0x5c;
311 Update(pad_block, block_size, context_outer);
314 Final(context_outer, any_digest);
324 unsigned char io_buffer[4096];
326 while ((actual_bytes = read(fd, io_buffer, 4096)) != 0) {
327 if (actual_bytes == -1) {
332 Update(io_buffer, actual_bytes, context);
334 Final(context, any_digest);
340 const int fd = open(filename.c_str(), O_RDONLY);
344 const bool result =
HashFd(fd, any_digest);
355 const string *str = ascii.
str;
358 MD5_Init(&md5_state);
359 MD5_Update(&md5_state, reinterpret_cast<const unsigned char *>(&(*str)[0]),
361 MD5_Final(
digest, &md5_state);
365 Md5::Md5(
const char *chars,
const unsigned length) {
369 MD5_Init(&md5_state);
370 MD5_Update(&md5_state, reinterpret_cast<const unsigned char *>(chars),
372 MD5_Final(
digest, &md5_state);
376 Md5::Md5(
const uint64_t lo,
const uint64_t hi) {
379 memcpy(
digest + 8, &hi, 8);
382 void Md5::ToIntPair(uint64_t *lo, uint64_t *hi)
const {
384 memcpy(hi,
digest + 8, 8);
395 #ifndef OPENSSL_API_INTERFACE_V09
398 result.reserve(2 * SHA256_DIGEST_LENGTH);
399 for (
unsigned i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
400 const char d1 =
digest[i] / 16;
401 const char d2 =
digest[i] % 16;
402 result.push_back(d1 + ((d1 <= 9) ?
'0' :
'a' - 10));
403 result.push_back(d2 + ((d2 <= 9) ?
'0' :
'a' - 10));
410 #ifdef OPENSSL_API_INTERFACE_V09
413 const int fd = open(filename.c_str(), O_RDONLY);
420 unsigned char io_buffer[4096];
422 while ((actual_bytes = read(fd, io_buffer, 4096)) != 0) {
423 if (actual_bytes == -1) {
429 SHA256_Update(&ctx, io_buffer, actual_bytes);
433 unsigned char digest[SHA256_DIGEST_LENGTH];
434 SHA256_Final(digest, &ctx);
439 string Sha256Mem(
const unsigned char *buffer,
const unsigned buffer_size) {
440 #ifdef OPENSSL_API_INTERFACE_V09
443 unsigned char digest[SHA256_DIGEST_LENGTH];
444 SHA256(buffer, buffer_size, digest);
450 return Sha256Mem(reinterpret_cast<const unsigned char *>(content.data()),
456 const std::string &content,
458 #ifdef OPENSSL_API_INTERFACE_V09
461 unsigned char digest[SHA256_DIGEST_LENGTH];
462 const unsigned block_size = 64;
463 const unsigned key_length = key.length();
464 unsigned char key_block[block_size];
465 memset(key_block, 0, block_size);
466 if (key_length > block_size) {
467 SHA256(reinterpret_cast<const unsigned char *>(key.data()), key_length,
470 if (key.length() > 0)
471 memcpy(key_block, key.data(), key_length);
474 unsigned char pad_block[block_size];
476 SHA256_CTX ctx_inner;
477 unsigned char digest_inner[SHA256_DIGEST_LENGTH];
478 SHA256_Init(&ctx_inner);
479 for (
unsigned i = 0; i < block_size; ++i)
480 pad_block[i] = key_block[i] ^ 0x36;
481 SHA256_Update(&ctx_inner, pad_block, block_size);
482 SHA256_Update(&ctx_inner, content.data(), content.length());
483 SHA256_Final(digest_inner, &ctx_inner);
486 SHA256_CTX ctx_outer;
487 SHA256_Init(&ctx_outer);
488 for (
unsigned i = 0; i < block_size; ++i)
489 pad_block[i] = key_block[i] ^ 0x5c;
490 SHA256_Update(&ctx_outer, pad_block, block_size);
491 SHA256_Update(&ctx_outer, digest_inner, SHA256_DIGEST_LENGTH);
493 SHA256_Final(digest, &ctx_outer);
495 return string(reinterpret_cast<const char *>(digest), SHA256_DIGEST_LENGTH);
502 #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)