⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hashing.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 2 页
字号:
    }  /* Zeroize sensitive information. */  memset (sctx, 0, sizeof (struct sha512_ctx));}/** * Hash block of given size. * * @param block the data to GNUNET_hash, length is given as a second argument * @param size the length of the data to GNUNET_hash * @param ret pointer to where to write the hashcode */voidGNUNET_hash (const void *block, unsigned int size, GNUNET_HashCode * ret){  struct sha512_ctx ctx;  sha512_init (&ctx);  sha512_update (&ctx, block, size);  sha512_final (&ctx, (unsigned char *) ret);}/** * Compute the GNUNET_hash of an entire file.  Does NOT load the entire file * into memory but instead processes it in blocks.  Very important for * large files. * * @return GNUNET_OK on success, GNUNET_SYSERR on error */intGNUNET_hash_file (struct GNUNET_GE_Context *ectx, const char *filename,                  GNUNET_HashCode * ret){  unsigned char *buf;  unsigned long long len;  unsigned long long pos;  unsigned int delta;  int fh;  struct sha512_ctx ctx;  if (GNUNET_OK != GNUNET_disk_file_test (ectx, filename))    return GNUNET_SYSERR;  if (GNUNET_OK != GNUNET_disk_file_size (ectx, filename, &len, GNUNET_NO))    return GNUNET_SYSERR;  fh = GNUNET_disk_file_open (ectx, filename, O_RDONLY | O_LARGEFILE);  if (fh == -1)    {      GNUNET_GE_LOG_STRERROR_FILE (ectx,                                   GNUNET_GE_ERROR | GNUNET_GE_USER |                                   GNUNET_GE_ADMIN | GNUNET_GE_REQUEST,                                   "open", filename);      return GNUNET_SYSERR;    }  sha512_init (&ctx);  pos = 0;  buf = GNUNET_malloc (65536);  while (pos < len)    {      delta = 65536;      if (len - pos < delta)        delta = len - pos;      if (delta != READ (fh, buf, delta))        {          GNUNET_GE_LOG_STRERROR_FILE (ectx,                                       GNUNET_GE_ERROR | GNUNET_GE_USER |                                       GNUNET_GE_ADMIN | GNUNET_GE_BULK,                                       "read", filename);          if (0 != CLOSE (fh))            GNUNET_GE_LOG_STRERROR_FILE (ectx,                                         GNUNET_GE_ERROR | GNUNET_GE_USER |                                         GNUNET_GE_ADMIN | GNUNET_GE_BULK,                                         "close", filename);          GNUNET_free (buf);          return GNUNET_SYSERR;        }      if (GNUNET_YES == GNUNET_shutdown_test ())        {          if (0 != CLOSE (fh))            GNUNET_GE_LOG_STRERROR_FILE (ectx,                                         GNUNET_GE_ERROR | GNUNET_GE_USER |                                         GNUNET_GE_ADMIN | GNUNET_GE_BULK,                                         "close", filename);          GNUNET_free (buf);          return GNUNET_SYSERR;        }      sha512_update (&ctx, buf, delta);      if (pos + delta > pos)        pos += delta;      else        break;    }  if (0 != CLOSE (fh))    GNUNET_GE_LOG_STRERROR_FILE (ectx,                                 GNUNET_GE_ERROR | GNUNET_GE_USER |                                 GNUNET_GE_ADMIN | GNUNET_GE_BULK, "close",                                 filename);  sha512_final (&ctx, (unsigned char *) ret);  GNUNET_free (buf);  return GNUNET_OK;}/* ***************** binary-ASCII encoding *************** *//** * 32 characters for encoding (GNUNET_hash => 32 characters) */static char *encTable__ = "0123456789ABCDEFGHIJKLMNOPQRSTUV";static unsigned intgetValue__ (unsigned char a){  if ((a >= '0') && (a <= '9'))    return a - '0';  if ((a >= 'A') && (a <= 'V'))    return (a - 'A' + 10);  return -1;}/** * Convert GNUNET_hash to ASCII encoding.  The ASCII encoding is rather * GNUnet specific.  It was chosen such that it only uses characters * in [0-9A-V], can be produced without complex arithmetics and uses a * small number of characters.  The GNUnet encoding uses 102 * characters plus a null terminator. * * @param block the GNUNET_hash code * @param result where to store the encoding (GNUNET_EncName can be *  safely cast to char*, a '\0' termination is set). */voidGNUNET_hash_to_enc (const GNUNET_HashCode * block, GNUNET_EncName * result){  unsigned int wpos;  unsigned int rpos;  unsigned int bits;  unsigned int vbit;  GNUNET_GE_ASSERT (NULL, block != NULL);  GNUNET_GE_ASSERT (NULL, result != NULL);  vbit = 0;  wpos = 0;  rpos = 0;  bits = 0;  while ((rpos < sizeof (GNUNET_HashCode)) || (vbit > 0))    {      if ((rpos < sizeof (GNUNET_HashCode)) && (vbit < 5))        {          bits = (bits << 8) | ((unsigned char *) block)[rpos++];       /* eat 8 more bits */          vbit += 8;        }      if (vbit < 5)        {          bits <<= (5 - vbit);  /* zero-padding */          GNUNET_GE_ASSERT (NULL, vbit == 2);   /* padding by 3: 512+3 mod 5 == 0 */          vbit = 5;        }      GNUNET_GE_ASSERT (NULL, wpos < sizeof (GNUNET_EncName) - 1);      result->encoding[wpos++] = encTable__[(bits >> (vbit - 5)) & 31];      vbit -= 5;    }  GNUNET_GE_ASSERT (NULL, wpos == sizeof (GNUNET_EncName) - 1);  GNUNET_GE_ASSERT (NULL, vbit == 0);  result->encoding[wpos] = '\0';}/** * Convert ASCII encoding back to GNUNET_hash * * @param enc the encoding * @param result where to store the GNUNET_hash code * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding */intGNUNET_enc_to_hash (const char *enc, GNUNET_HashCode * result){  unsigned int rpos;  unsigned int wpos;  unsigned int bits;  unsigned int vbit;  if (strlen (enc) != sizeof (GNUNET_EncName) - 1)    return GNUNET_SYSERR;  vbit = 2;                     /* padding! */  wpos = sizeof (GNUNET_HashCode);  rpos = sizeof (GNUNET_EncName) - 1;  bits = getValue__ (enc[--rpos]) >> 3;  while (wpos > 0)    {      GNUNET_GE_ASSERT (NULL, rpos > 0);      bits = (getValue__ (enc[--rpos]) << vbit) | bits;      vbit += 5;      if (vbit >= 8)        {          ((unsigned char *) result)[--wpos] = (unsigned char) bits;          bits >>= 8;          vbit -= 8;        }    }  GNUNET_GE_ASSERT (NULL, rpos == 0);  GNUNET_GE_ASSERT (NULL, vbit == 0);  return GNUNET_OK;}/** * Compute the distance between 2 hashcodes.  The computation must be * fast, not involve bits[0] or bits[4] (they're used elsewhere), and be * somewhat consistent. And of course, the result should be a positive * number. * * @returns a positive number which is a measure for *  hashcode proximity. */unsigned intGNUNET_hash_distance_u32 (const GNUNET_HashCode * a,                          const GNUNET_HashCode * b){  unsigned int x = (a->bits[1] - b->bits[1]) >> 16;  return ((x * x) >> 16);}voidGNUNET_create_random_hash (GNUNET_HashCode * result){  int i;  for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0;       i--)    result->bits[i] = rand ();}voidGNUNET_hash_difference (const GNUNET_HashCode * a, const GNUNET_HashCode * b,                        GNUNET_HashCode * result){  int i;  for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0;       i--)    result->bits[i] = b->bits[i] - a->bits[i];}voidGNUNET_hash_sum (const GNUNET_HashCode * a,                 const GNUNET_HashCode * delta, GNUNET_HashCode * result){  int i;  for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0;       i--)    result->bits[i] = delta->bits[i] + a->bits[i];}voidGNUNET_hash_xor (const GNUNET_HashCode * a,                 const GNUNET_HashCode * b, GNUNET_HashCode * result){  int i;  for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0;       i--)    result->bits[i] = a->bits[i] ^ b->bits[i];}/** * Convert a hashcode into a key. */voidGNUNET_hash_to_AES_key (const GNUNET_HashCode * hc,                        GNUNET_AES_SessionKey * skey,                        GNUNET_AES_InitializationVector * iv){  GNUNET_GE_ASSERT (NULL,                    sizeof (GNUNET_HashCode) >=                    GNUNET_SESSIONKEY_LEN +                    sizeof (GNUNET_AES_InitializationVector));  memcpy (skey, hc, GNUNET_SESSIONKEY_LEN);  skey->crc32 = htonl (GNUNET_crc32_n (skey, GNUNET_SESSIONKEY_LEN));  memcpy (iv, &((char *) hc)[GNUNET_SESSIONKEY_LEN],          sizeof (GNUNET_AES_InitializationVector));}/** * Obtain a bit from a hashcode. * @param code the GNUNET_hash to index bit-wise * @param bit index into the hashcode, [0...511] * @return Bit \a bit from hashcode \a code, -1 for invalid index */intGNUNET_hash_get_bit (const GNUNET_HashCode * code, unsigned int bit){  if (bit >= 8 * sizeof (GNUNET_HashCode))    {      GNUNET_GE_ASSERT (NULL, 0);      return -1;                /* error */    }  return (((unsigned char *) code)[bit >> 3] & (1 << bit & 7)) > 0;}/** * Compare function for HashCodes, producing a total ordering * of all hashcodes. * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2. */intGNUNET_hash_cmp (const GNUNET_HashCode * h1, const GNUNET_HashCode * h2){  unsigned int *i1;  unsigned int *i2;  int i;  i1 = (unsigned int *) h1;  i2 = (unsigned int *) h2;  for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0;       i--)    {      if (i1[i] > i2[i])        return 1;      if (i1[i] < i2[i])        return -1;    }  return 0;}/** * Find out which of the two GNUNET_hash codes is closer to target * in the XOR metric (Kademlia). * @return -1 if h1 is closer, 1 if h2 is closer and 0 if h1==h2. */intGNUNET_hash_xorcmp (const GNUNET_HashCode * h1,                    const GNUNET_HashCode * h2,                    const GNUNET_HashCode * target){  int i;  unsigned int d1;  unsigned int d2;  for (i = sizeof (GNUNET_HashCode) / sizeof (unsigned int) - 1; i >= 0; i--)    {      d1 = ((unsigned int *) h1)[i] ^ ((unsigned int *) target)[i];      d2 = ((unsigned int *) h2)[i] ^ ((unsigned int *) target)[i];      if (d1 > d2)        return 1;      else if (d1 < d2)        return -1;    }  return 0;}/* end of hashing.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -