hash_util.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. from hashlib import blake2b, shake_128, md5, sha256, sha1
  2. import os
  3. from base64 import b64encode, b64decode, b85encode, b85decode
  4. import base32_lib as b32
  5. DIGEST_SIZE_BYTES = 3
  6. DIGEST_SIZE_BITMASK = 0xffffff
  7. DIGEST_SIZE_SIGNED_TO_UNSIGNED_BITMASK = 0x1ffffff
  8. DIGEST_SIZE_SIGNED_TO_UNSIGNED_BIT = 0x1000000
  9. DIGEST_SIZE_NIBBLES = DIGEST_SIZE_BYTES * 2
  10. B64ALTCHARS = b'.-'
  11. def sha1hash(data: str):
  12. return sha1(data.encode("utf-8"), usedforsecurity=False).hexdigest()[:DIGEST_SIZE_BYTES]
  13. def sha256hash(data: str):
  14. return sha256(data.encode("utf-8"), usedforsecurity=False).hexdigest()[:DIGEST_SIZE_BYTES]
  15. def md5hash(data: str):
  16. return md5(data.encode("utf-8"), usedforsecurity=False).hexdigest()[:DIGEST_SIZE_BYTES]
  17. def shake(data: str):
  18. return shake_128(data.encode("utf-8"), usedforsecurity=False).hexdigest(DIGEST_SIZE_BYTES)
  19. def blake(data: bytes, person: bytes = None) -> bytes:
  20. return blake2b(
  21. data,
  22. usedforsecurity=False,
  23. digest_size=DIGEST_SIZE_BYTES,
  24. person=person
  25. ).digest()
  26. def blake_file(path: str, person: bytes = None, root: str ='rest/static') -> bytes:
  27. fd = os.open(f'{root}/{path}', os.O_RDONLY, 0o600)
  28. with open(fd, "rb") as f:
  29. f.seek(0)
  30. _blake = blake2b(usedforsecurity=False, digest_size=DIGEST_SIZE_BYTES, person='upload'.encode('utf-8'))
  31. while f.peek(1):
  32. _blake.update(f.read(1024))
  33. return _blake.digest()
  34. def python(data: str):
  35. return hash(data)
  36. def normalize_hash(_hash: int) -> int:
  37. #hex = hash_to_hex(_hash)
  38. #return int(hex, 16)
  39. #_bytes = _hash.to_bytes(8, byteorder='big', signed=True)
  40. #return bytes_to_hash(_bytes)
  41. return _hash & DIGEST_SIZE_BITMASK
  42. def normalize_bytes(_bytes: bytes) -> bytes:
  43. return (b'\x00' * DIGEST_SIZE_BYTES + _bytes)[-DIGEST_SIZE_BYTES:]
  44. def normalize_hex(_hex: str) -> str:
  45. #_bytes = hex_to_bytes(hex)
  46. #return _bytes.hex()
  47. return _hex.zfill(DIGEST_SIZE_NIBBLES)[-DIGEST_SIZE_NIBBLES:]
  48. def hex_to_bytes(_hex: str) -> bytes:
  49. _bytes = bytes.fromhex(_hex.zfill(DIGEST_SIZE_NIBBLES))
  50. return normalize_bytes(_bytes)
  51. def bytes_to_hex(_bytes: bytes) -> str:
  52. return normalize_bytes(_bytes).hex()
  53. def hash_to_bytes(_hash: int) -> bytes:
  54. _bytes = _hash.to_bytes(8, byteorder='big', signed=True)
  55. return normalize_bytes(_bytes)
  56. def bytes_to_hash(_bytes: bytes) -> int:
  57. norm = normalize_bytes(_bytes)
  58. return int.from_bytes(norm, byteorder='big', signed=False)
  59. def hash_to_hex(_hash: int) -> str:
  60. #return hash_to_bytes(_hash).hex()
  61. #return normalize_hex(
  62. #return f"{_hash + (1 << 64):x}"[-4:]
  63. #return hex(_hash + (1<<64))[2:][-4:]
  64. #return f"{_hash & 0xffff:04x}"
  65. return hex((_hash|DIGEST_SIZE_SIGNED_TO_UNSIGNED_BIT) & DIGEST_SIZE_SIGNED_TO_UNSIGNED_BITMASK)[3:]
  66. def hex_to_hash(_hex: str) -> int:
  67. #_bytes = bytes.fromhex(hex.zfill(4))
  68. #return bytes_to_hash(_bytes)
  69. #return int(normalize_hex(hex), 16)
  70. return int(_hex, 16) & DIGEST_SIZE_BITMASK
  71. def remove_padding(f):
  72. def wrap(*args, **kwargs):
  73. return f(*args, **kwargs).split('=')[0]
  74. return wrap
  75. def fix_padding(f):
  76. def wrap(_b64, *args, **kwargs):
  77. pad = (4 - len(_b64)) % 4
  78. fixed = _b64 + '='*pad
  79. return f(fixed, *args, **kwargs)
  80. return wrap
  81. def normalize_base32(_b32: str):
  82. return _b32.upper().zfill(DIGEST_SIZE_BYTES*8//5+1)
  83. def add_padding_base32(f):
  84. def wrap(*args, **kwargs):
  85. return normalize_base32(f(*args, **kwargs))
  86. return wrap
  87. @remove_padding
  88. def hash_to_base64(_hash: int) -> str:
  89. return b64encode(hash_to_bytes(_hash), altchars=B64ALTCHARS).decode("utf-8")
  90. @remove_padding
  91. def hex_to_base64(_hex: str) -> str:
  92. return b64encode(hex_to_bytes(_hex), altchars=B64ALTCHARS).decode("utf-8")
  93. @remove_padding
  94. def bytes_to_base64(_bytes: str) -> str:
  95. return b64encode(normalize_bytes(_bytes), altchars=B64ALTCHARS).decode("utf-8")
  96. @fix_padding
  97. def base64_to_hash(_b64: str) -> str:
  98. return bytes_to_hash(b64decode(_b64, altchars=B64ALTCHARS))
  99. @fix_padding
  100. def base64_to_hex(_b64: str) -> str:
  101. return bytes_to_hex(b64decode(_b64, altchars=B64ALTCHARS))
  102. @fix_padding
  103. def base64_to_bytes(_b64: str) -> str:
  104. return normalize_bytes(b64decode(_b64, altchars=B64ALTCHARS))
  105. #@remove_padding
  106. def hash_to_base85(_hash: int) -> str:
  107. return b85encode(hash_to_bytes(_hash)).decode("utf-8")
  108. #@remove_padding
  109. def hex_to_base85(_hex: str) -> str:
  110. return b85encode(hex_to_bytes(_hex)).decode("utf-8")
  111. #@remove_padding
  112. def bytes_to_base85(_bytes: str) -> str:
  113. return b85encode(normalize_bytes(_bytes)).decode("utf-8")
  114. #@fix_padding
  115. def base85_to_hash(_b64: str) -> str:
  116. return bytes_to_hash(b85decode(_b64))
  117. #@fix_padding
  118. def base85_to_hex(_b64: str) -> str:
  119. return bytes_to_hex(b85decode(_b64))
  120. #@fix_padding
  121. def base85_to_bytes(_b64: str) -> str:
  122. return normalize_bytes(b85decode(_b64))
  123. @add_padding_base32
  124. def hash_to_base32(_hash: int) -> str:
  125. return b32.encode(_hash & DIGEST_SIZE_BITMASK)
  126. @add_padding_base32
  127. def hex_to_base32(_hex: str) -> str:
  128. return b32.encode(hex_to_hash(_hex))
  129. @add_padding_base32
  130. def bytes_to_base32(_bytes: bytes) -> str:
  131. return b32.encode(bytes_to_hash(_bytes))
  132. #@fix_padding
  133. def base32_to_hash(_b64: str) -> str:
  134. return b32.decode(_b64)
  135. #@fix_padding
  136. def base32_to_hex(_b64: str) -> str:
  137. return hash_to_hex(base32_to_hash(_b64))
  138. #@fix_padding
  139. def base32_to_bytes(_b64: str) -> str:
  140. return hash_to_bytes(base32_to_hash(_b64))