1
# Written by John Hoffman
2
# based on code by Uoti Urpala
3
# see LICENSE.txt for license information
5
from __future__ import generators # for python 2.2
6
from random import randrange,randint,seed
11
urandom = lambda x: ''.join([chr(randint(0,255)) for i in xrange(x)])
21
from Crypto.Cipher import ARC4
27
DH_PRIME = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563
28
PAD_MAX = 200 # less than protocol maximum, and later assumed to be < 256
32
return long(x.encode('hex'), 16)
35
x = hex(x).lstrip('0x').rstrip('Ll')
36
x = '0'*(192 - len(x)) + x
37
return x.decode('hex')
40
def __init__(self, initiator, disable_crypto = False):
41
self.initiator = initiator
42
self.disable_crypto = disable_crypto
43
if not disable_crypto and not CRYPTO_OK:
44
raise NotImplementedError, "attempt to run encryption w/ none installed"
45
self.privkey = bytetonum(urandom(KEY_LENGTH/8))
46
self.pubkey = numtobyte(pow(2, self.privkey, DH_PRIME))
47
self.keylength = DH_BYTES
48
self._VC_pattern = None
50
def received_key(self, k):
51
self.S = numtobyte(pow(bytetonum(k), self.privkey, DH_PRIME))
52
self.block3a = sha('req1'+self.S).digest()
53
self.block3bkey = sha('req3'+self.S).digest()
56
def _gen_block3b(self, SKEY):
57
a = sha('req2'+SKEY).digest()
58
return ''.join([ chr(ord(a[i])^ord(self.block3bkey[i]))
59
for i in xrange(20) ])
61
def test_skey(self, s, SKEY):
62
block3b = self._gen_block3b(SKEY)
65
self.block3b = block3b
66
if not self.disable_crypto:
70
def set_skey(self, SKEY):
72
self.block3b = self._gen_block3b(SKEY)
73
crypta = ARC4.new(sha('keyA'+self.S+SKEY).digest())
74
cryptb = ARC4.new(sha('keyB'+self.S+SKEY).digest())
76
self.encrypt = crypta.encrypt
77
self.decrypt = cryptb.decrypt
79
self.encrypt = cryptb.encrypt
80
self.decrypt = crypta.decrypt
81
self.encrypt('x'*1024) # discard first 1024 bytes
82
self.decrypt('x'*1024)
85
if not self._VC_pattern:
86
self._VC_pattern = self.decrypt('\x00'*8)
87
return self._VC_pattern
91
self._read(self.decrypt(s))
94
self._write(self.encrypt(s))
96
def setrawaccess(self, _read, _write):
101
return urandom(randrange(PAD_MAX-16)+16)