You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bignum.py 1.9KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #!/usr/bin/env python3
  2. #
  3. # Distributed under the MIT software license, see the accompanying
  4. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5. """Big number routines.
  6. This file is copied from python-bitcoinlib.
  7. """
  8. import struct
  9. # generic big endian MPI format
  10. def bn_bytes(v, have_ext=False):
  11. ext = 0
  12. if have_ext:
  13. ext = 1
  14. return ((v.bit_length()+7)//8) + ext
  15. def bn2bin(v):
  16. s = bytearray()
  17. i = bn_bytes(v)
  18. while i > 0:
  19. s.append((v >> ((i-1) * 8)) & 0xff)
  20. i -= 1
  21. return s
  22. def bin2bn(s):
  23. l = 0
  24. for ch in s:
  25. l = (l << 8) | ch
  26. return l
  27. def bn2mpi(v):
  28. have_ext = False
  29. if v.bit_length() > 0:
  30. have_ext = (v.bit_length() & 0x07) == 0
  31. neg = False
  32. if v < 0:
  33. neg = True
  34. v = -v
  35. s = struct.pack(b">I", bn_bytes(v, have_ext))
  36. ext = bytearray()
  37. if have_ext:
  38. ext.append(0)
  39. v_bin = bn2bin(v)
  40. if neg:
  41. if have_ext:
  42. ext[0] |= 0x80
  43. else:
  44. v_bin[0] |= 0x80
  45. return s + ext + v_bin
  46. def mpi2bn(s):
  47. if len(s) < 4:
  48. return None
  49. s_size = bytes(s[:4])
  50. v_len = struct.unpack(b">I", s_size)[0]
  51. if len(s) != (v_len + 4):
  52. return None
  53. if v_len == 0:
  54. return 0
  55. v_str = bytearray(s[4:])
  56. neg = False
  57. i = v_str[0]
  58. if i & 0x80:
  59. neg = True
  60. i &= ~0x80
  61. v_str[0] = i
  62. v = bin2bn(v_str)
  63. if neg:
  64. return -v
  65. return v
  66. # bitcoin-specific little endian format, with implicit size
  67. def mpi2vch(s):
  68. r = s[4:] # strip size
  69. r = r[::-1] # reverse string, converting BE->LE
  70. return r
  71. def bn2vch(v):
  72. return bytes(mpi2vch(bn2mpi(v)))
  73. def vch2mpi(s):
  74. r = struct.pack(b">I", len(s)) # size
  75. r += s[::-1] # reverse string, converting LE->BE
  76. return r
  77. def vch2bn(s):
  78. return mpi2bn(vch2mpi(s))