BTcrypto.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. # Written by John Hoffman
  2. # based on code by Uoti Urpala
  3. # see LICENSE.txt for license information
  4. from __future__ import generators # for python 2.2
  5. from random import randrange,randint,seed
  6. try:
  7. from os import urandom
  8. except:
  9. seed()
  10. urandom = lambda x: ''.join([chr(randint(0,255)) for i in xrange(x)])
  11. from sha import sha
  12. try:
  13. True
  14. except:
  15. True = 1
  16. False = 0
  17. try:
  18. from Crypto.Cipher import ARC4
  19. CRYPTO_OK = True
  20. except:
  21. CRYPTO_OK = False
  22. KEY_LENGTH = 160
  23. DH_PRIME = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563
  24. PAD_MAX = 200 # less than protocol maximum, and later assumed to be < 256
  25. DH_BYTES = 96
  26. def bytetonum(x):
  27. return long(x.encode('hex'), 16)
  28. def numtobyte(x):
  29. x = hex(x).lstrip('0x').rstrip('Ll')
  30. x = '0'*(192 - len(x)) + x
  31. return x.decode('hex')
  32. class Crypto:
  33. def __init__(self, initiator, disable_crypto = False):
  34. self.initiator = initiator
  35. self.disable_crypto = disable_crypto
  36. if not disable_crypto and not CRYPTO_OK:
  37. raise NotImplementedError, "attempt to run encryption w/ none installed"
  38. self.privkey = bytetonum(urandom(KEY_LENGTH/8))
  39. self.pubkey = numtobyte(pow(2, self.privkey, DH_PRIME))
  40. self.keylength = DH_BYTES
  41. self._VC_pattern = None
  42. def received_key(self, k):
  43. self.S = numtobyte(pow(bytetonum(k), self.privkey, DH_PRIME))
  44. self.block3a = sha('req1'+self.S).digest()
  45. self.block3bkey = sha('req3'+self.S).digest()
  46. self.block3b = None
  47. def _gen_block3b(self, SKEY):
  48. a = sha('req2'+SKEY).digest()
  49. return ''.join([ chr(ord(a[i])^ord(self.block3bkey[i]))
  50. for i in xrange(20) ])
  51. def test_skey(self, s, SKEY):
  52. block3b = self._gen_block3b(SKEY)
  53. if block3b != s:
  54. return False
  55. self.block3b = block3b
  56. if not self.disable_crypto:
  57. self.set_skey(SKEY)
  58. return True
  59. def set_skey(self, SKEY):
  60. if not self.block3b:
  61. self.block3b = self._gen_block3b(SKEY)
  62. crypta = ARC4.new(sha('keyA'+self.S+SKEY).digest())
  63. cryptb = ARC4.new(sha('keyB'+self.S+SKEY).digest())
  64. if self.initiator:
  65. self.encrypt = crypta.encrypt
  66. self.decrypt = cryptb.decrypt
  67. else:
  68. self.encrypt = cryptb.encrypt
  69. self.decrypt = crypta.decrypt
  70. self.encrypt('x'*1024) # discard first 1024 bytes
  71. self.decrypt('x'*1024)
  72. def VC_pattern(self):
  73. if not self._VC_pattern:
  74. self._VC_pattern = self.decrypt('\x00'*8)
  75. return self._VC_pattern
  76. def read(self, s):
  77. self._read(self.decrypt(s))
  78. def write(self, s):
  79. self._write(self.encrypt(s))
  80. def setrawaccess(self, _read, _write):
  81. self._read = _read
  82. self._write = _write
  83. def padding(self):
  84. return urandom(randrange(PAD_MAX-16)+16)