| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- # Written by John Hoffman
- # based on code by Uoti Urpala
- # see LICENSE.txt for license information
- from __future__ import generators # for python 2.2
- from random import randrange,randint,seed
- try:
- from os import urandom
- except:
- seed()
- urandom = lambda x: ''.join([chr(randint(0,255)) for i in xrange(x)])
- from sha import sha
- try:
- True
- except:
- True = 1
- False = 0
-
- try:
- from Crypto.Cipher import ARC4
- CRYPTO_OK = True
- except:
- CRYPTO_OK = False
- KEY_LENGTH = 160
- DH_PRIME = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563
- PAD_MAX = 200 # less than protocol maximum, and later assumed to be < 256
- DH_BYTES = 96
- def bytetonum(x):
- return long(x.encode('hex'), 16)
- def numtobyte(x):
- x = hex(x).lstrip('0x').rstrip('Ll')
- x = '0'*(192 - len(x)) + x
- return x.decode('hex')
- class Crypto:
- def __init__(self, initiator, disable_crypto = False):
- self.initiator = initiator
- self.disable_crypto = disable_crypto
- if not disable_crypto and not CRYPTO_OK:
- raise NotImplementedError, "attempt to run encryption w/ none installed"
- self.privkey = bytetonum(urandom(KEY_LENGTH/8))
- self.pubkey = numtobyte(pow(2, self.privkey, DH_PRIME))
- self.keylength = DH_BYTES
- self._VC_pattern = None
- def received_key(self, k):
- self.S = numtobyte(pow(bytetonum(k), self.privkey, DH_PRIME))
- self.block3a = sha('req1'+self.S).digest()
- self.block3bkey = sha('req3'+self.S).digest()
- self.block3b = None
- def _gen_block3b(self, SKEY):
- a = sha('req2'+SKEY).digest()
- return ''.join([ chr(ord(a[i])^ord(self.block3bkey[i]))
- for i in xrange(20) ])
- def test_skey(self, s, SKEY):
- block3b = self._gen_block3b(SKEY)
- if block3b != s:
- return False
- self.block3b = block3b
- if not self.disable_crypto:
- self.set_skey(SKEY)
- return True
- def set_skey(self, SKEY):
- if not self.block3b:
- self.block3b = self._gen_block3b(SKEY)
- crypta = ARC4.new(sha('keyA'+self.S+SKEY).digest())
- cryptb = ARC4.new(sha('keyB'+self.S+SKEY).digest())
- if self.initiator:
- self.encrypt = crypta.encrypt
- self.decrypt = cryptb.decrypt
- else:
- self.encrypt = cryptb.encrypt
- self.decrypt = crypta.decrypt
- self.encrypt('x'*1024) # discard first 1024 bytes
- self.decrypt('x'*1024)
- def VC_pattern(self):
- if not self._VC_pattern:
- self._VC_pattern = self.decrypt('\x00'*8)
- return self._VC_pattern
- def read(self, s):
- self._read(self.decrypt(s))
- def write(self, s):
- self._write(self.encrypt(s))
- def setrawaccess(self, _read, _write):
- self._read = _read
- self._write = _write
- def padding(self):
- return urandom(randrange(PAD_MAX-16)+16)
-
-
|