【问题标题】:Convert sha256 to smaller uint type将 sha256 转换为更小的 uint 类型
【发布时间】:2021-12-07 01:27:44
【问题描述】:

我在 c 中实现了一个哈希表,我选择了我需要存储的文件的 sha256 哈希作为键。问题是我需要将键转换为可重用索引以插入哈希表。我很难重新散列密钥,但这样我会增加重叠值的可能性。有没有办法使用这个哈希作为表的键?

sha256 存储为 BYTE[32] 或可以转换为字符串

void* ht_get(ht* table, const char *key) {
    size_t index = magicfunction(key);

    while (table->entries[index].key != NULL) {
        if (strcmp(key, table->entries[index].key) == 0) {
            // Found key, return value.
            return table->entries[index].value;
        }
        // Key wasn't in this slot, move to next (linear probing).
        index++;
        if (index >= table->capacity) {
            index = 0;
        }
    }
    return NULL;
 }

【问题讨论】:

  • 如果是 32 字节,则为 32 字节——无论它是什么类型,它都不能用作索引,因为您根本无法为按 32 字节索引的表提供足够的内存。您必须使用较小的尺寸,这会增加碰撞。不过,您不需要重新散列它,您可以简单地使用任意数量的字节。
  • 除非您可以分配大小为 1e77 的表,否则您将不得不丢弃部分哈希,然后处理由此产生的哈希冲突。
  • 由于 sha256 被认为是一个很好的随机数生成器,我建议只使用前 8 个字节或 size_t 的大小。当然,之后不要忘记index %= table->capacity;
  • 您需要处理潜在的恶意数据吗?也就是说,您是否担心攻击者可能会选择您散列的数据,从而导致散列冲突并减少表的有效大小?如果您需要抵抗算法复杂性攻击,您可能需要使用随机方法来减少哈希空间。
  • @Cosinus 这将是一种方法。另一种方法是在“压缩”SHA256 哈希的过程中使用一些随机性。您可以使用 xxhash 之类的东西来压缩随机种子,然后是 SHA256 哈希。 (由于defend against algorithmic complexity attacks,这就是 XRP Ledger 的哈希表。)

标签: c hashtable sha256


【解决方案1】:

当我在 C 中需要一个绝对极简的 hashmap 时,我通常会这样做:

#include <stddef.h>
#include <string.h>
#include <stdio.h>

struct hmap_entry {
  const char *key;
  /* Or in your case: */
  /* char key[SIZE_OF_SHA256]; */

  void *payload;
};

#define HMAP_ENTRY_CNT 256
struct hmap {
  struct hmap_entry entries[HMAP_ENTRY_CNT];
};

static size_t str_hash(const char *s) {
  size_t hash = 0;
  while(*s) {
    hash = (hash << 7) ^ (size_t)*s++ ^ hash;
  }
  return hash;
}

static struct hmap_entry *hmap_search_entry(struct hmap *map
    , const char *key)
{
  size_t hash = str_hash(key);
  /* Or in your case: */
  /* size_t hash = 0; memcpy(&hash, key, sizeof(key)) */

  hash = hash % HMAP_ENTRY_CNT;

  struct hmap_entry *e = NULL;
  while(1) {
    e = map->entries + hash;

    if(e->key == NULL
        || strcmp(key, e->key) == 0) {
      break;
    }
    /* Or in your case: */
    /* if(e->key == NULL
          || memcmp(key, e->key, SIZE_OF_SHA256) == 0) {
        break;
       }
     */


    hash = (hash + 1) % HMAP_ENTRY_CNT;
  }
  return e;
}

这就是我使用它的方式:

int main()
{
  struct hmap_entry *e;
  struct hmap map = {};

  /* insert foo */
  e = hmap_search_entry(&map, "foo");
  e->key = "foo";
  e->payload = "hello world";

  /* insert bar */
  e = hmap_search_entry(&map, "bar");
  e->key = "bar";
  e->payload = "Something else";

  /* get foo */
  e = hmap_search_entry(&map, "foo");
  if(e->key) {
    printf("Value of \"%s\" is \"%s\"\n", e->key, (const char *)e->payload);
  }
  else {
    printf("Not found!\n");
  }

  /* get bar */
  e = hmap_search_entry(&map, "bar");
  if(e->key) {
    printf("Value of \"%s\" is \"%s\"\n", e->key, (const char *)e->payload);
  }
  else {
    printf("Not found!\n");
  }

  /* get test */
  e = hmap_search_entry(&map, "test");
  if(e->key) {
    printf("Value of \"%s\" is \"%s\"\n", e->key, (const char *)e->payload);
  }
  else {
    printf("Not found!\n");
  }

  return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 2016-02-13
    • 2013-03-05
    • 2012-11-06
    • 2014-07-31
    相关资源
    最近更新 更多