sha256.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
  4. # Copyright (C)2013-2019 The MMGen Project <mmgen@tuta.io>
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. """
  19. sha256.py: custom sha256 implementation for Zcash
  20. """
  21. # Sha256 code ported from JavaScript, originally here:
  22. # CryptoJS v3.1.2 code.google.com/p/crypto-js
  23. # (c) 2009-2013 by Jeff Mott. All rights reserved.
  24. # code.google.com/p/crypto-js/wiki/License
  25. # via here:
  26. # https://www.npmjs.com/package/sha256
  27. # and here:
  28. # https://github.com/howardwu/zaddr
  29. from binascii import hexlify
  30. class Sha256(object):
  31. def initConstants():
  32. import math
  33. def isPrime(n):
  34. for factor in range(2,int(math.sqrt(n))+1):
  35. if not (n % factor): return False
  36. return True
  37. def getFractionalBits(n):
  38. return int((n - int(n)) * 0x100000000)
  39. k = [0] * 64
  40. n,nPrime = 2,0
  41. while nPrime < 64:
  42. if isPrime(n):
  43. k[nPrime] = getFractionalBits(math.pow(n, 1 / 3))
  44. nPrime += 1
  45. n += 1
  46. return k
  47. K = initConstants()
  48. # preprocess: True=Sha256(), False=Sha256Compress()
  49. def __init__(self,message,preprocess=True):
  50. self.H = [0x6A09E667,0xBB67AE85,0x3C6EF372,0xA54FF53A,0x510E527F,0x9B05688C,0x1F83D9AB,0x5BE0CD19]
  51. self.M = message
  52. self.W = [0] * 64
  53. (self.bytesToWords,self.preprocessBlock)[preprocess]()
  54. # self.initConstants()
  55. self.compute()
  56. def digest(self):
  57. self.M = self.H
  58. self.wordsToBytes()
  59. return self.M
  60. def hexdigest(self):
  61. return hexlify(self.digest())
  62. def bytesToWords(self):
  63. assert type(self.M) in (bytes,bytearray,list)
  64. words = [0] * (len(self.M) // 4 + len(self.M) % 4)
  65. b = 0
  66. for i in range(len(self.M)):
  67. words[b >> 5] |= self.M[i] << (24 - b % 32)
  68. b += 8
  69. self.M = words
  70. def wordsToBytes(self):
  71. assert type(self.M) == list and len(self.M) == 8
  72. self.M = bytes([(self.M[b >> 5] >> (24 - b % 32) & 0xff) for b in range(0,len(self.M)*32,8)])
  73. def preprocessBlock(self):
  74. def lshift(a,b): return (a << b) & 0xffffffff
  75. assert type(self.M) in (bytes,bytearray)
  76. l = len(self.M) * 8
  77. self.bytesToWords()
  78. last_idx = lshift((l + 64 >> 9),4) + 15
  79. self.M.extend([0] * (last_idx - len(self.M) + 1))
  80. self.M[l >> 5] |= lshift(0x80, (24 - l % 32))
  81. self.M[last_idx] = l
  82. def compute(self):
  83. assert type(self.M) == list
  84. for i in range(0,len(self.M),16):
  85. self.processBlock(i)
  86. def processBlock(self,offset):
  87. def lshift(a,b): return (a << b) & 0xffffffff
  88. def sumr(a,b): return (a + b) & 0xffffffff
  89. a,b,c,d,e,f,g,h = [self.H[i] for i in range(8)] # Working variables
  90. for i in range(64):
  91. if i < 16:
  92. self.W[i] = self.M[offset + i]
  93. else:
  94. gamma0x = self.W[i - 15]
  95. gamma0 = ( (lshift(gamma0x,25) | (gamma0x >> 7)) ^
  96. (lshift(gamma0x,14) | (gamma0x >> 18)) ^
  97. (gamma0x >> 3) )
  98. gamma1x = self.W[i - 2]
  99. gamma1 = ( (lshift(gamma1x,15) | (gamma1x >> 17)) ^
  100. (lshift(gamma1x,13) | (gamma1x >> 19)) ^
  101. (gamma1x >> 10) )
  102. self.W[i] = sumr(sumr(sumr(gamma0,self.W[i - 7]),gamma1),self.W[i - 16])
  103. ch = (e & f) ^ (~e & g)
  104. maj = (a & b) ^ (a & c) ^ (b & c)
  105. sigma0 = (lshift(a,30) | (a >> 2)) ^ (lshift(a,19) | (a >> 13)) ^ (lshift(a,10) | (a >> 22))
  106. sigma1 = (lshift(e,26) | (e >> 6)) ^ (lshift(e,21) | (e >> 11)) ^ (lshift(e,7) | (e >> 25))
  107. t1 = sumr(sumr(sumr(sumr(h,sigma1),ch),self.K[i]),self.W[i])
  108. t2 = sumr(sigma0,maj)
  109. h = g
  110. g = f
  111. f = e
  112. e = sumr(d,t1)
  113. d = c
  114. c = b
  115. b = a
  116. a = sumr(t1,t2)
  117. # Intermediate hash value
  118. for n,v in enumerate([a,b,c,d,e,f,g,h]):
  119. self.H[n] = sumr(self.H[n],v)