diff --git a/kex_gex.py b/kex_gex.py index cf4b6d3..2b6e11c 100644 --- a/kex_gex.py +++ b/kex_gex.py @@ -4,7 +4,8 @@ # are provided by the server. a bit more work is required on our side (and a # LOT more on the server side). -from message import Message, inflate_long, deflate_long +from message import Message +from util import inflate_long, deflate_long, generate_prime from secsh import SSHException from transport import MSG_NEWKEYS from Crypto.Hash import SHA @@ -95,10 +96,11 @@ class KexGex(object): # generate prime while 1: # does not work FIXME + # the problem is that it's too fscking SLOW self.transport.log(DEBUG, 'stir...') self.transport.randpool.stir() self.transport.log(DEBUG, 'get-prime %d...' % preferred) - self.p = number.getPrime(preferred, self.transport.randpool.get_bytes) + self.p = generate_prime(preferred, self.transport.randpool) self.transport.log(DEBUG, 'got ' + repr(self.p)) if number.isPrime((self.p - 1) // 2): break diff --git a/util.py b/util.py index 2834972..fd78af3 100644 --- a/util.py +++ b/util.py @@ -1,6 +1,7 @@ #!/usr/bin/python -import struct +import sys, struct, traceback +from Crypto.Util import number def inflate_long(s, always_positive=0): "turns a normalized byte string into a long-int (adapted from Crypto.Util.number)" @@ -87,3 +88,30 @@ def safe_string(s): return out # ''.join([['%%%02X' % ord(c), c][(ord(c) >= 32) and (ord(c) <= 127)] for c in s]) + +def bit_length(n): + norm = deflate_long(n, 0) + hbyte = ord(norm[0]) + bitlen = len(norm) * 8 + while not (hbyte & 0x80): + hbyte <<= 1 + bitlen -= 1 + return bitlen + +def generate_prime(bits, randpool): + hbyte_mask = pow(2, bits % 8) - 1 + x = randpool.get_bytes((bits+7) // 8) + if hbyte_mask > 0: + x = chr(ord(x[0]) & hbyte_mask) + x[1:] + n = inflate_long(x, 1) + n |= 1 + n |= (1 << (bits - 1)) + while 1: + # loop catches the case where we increment n into a higher bit-range + while not number.isPrime(n): + n += 2 + if bit_length(n) == bits: + return n + +def tb_strings(): + return ''.join(traceback.format_exception(*sys.exc_info())).split('\n')