def ssh_KEX_DH_GEX_REQUEST_OLD(self, packet): if self.ignoreNextPacket: self.ignoreNextPacket = 0 return if self.kexAlg == 'diffie-hellman-group1-sha1': # this is really KEXDH_INIT clientDHPubKey, foo = getMP(packet) y = Util.number.getRandomNumber(16, entropy.get_bytes) f = pow(DH_GENERATOR, y, DH_PRIME) sharedSecret = _MPpow(clientDHPubKey, y, DH_PRIME) h = sha.new() h.update(NS(self.otherVersionString)) h.update(NS(self.ourVersionString)) h.update(NS(self.clientKexInitPayload)) h.update(NS(self.ourKexInitPayload)) h.update(NS(self.factory.publicKeys[self.keyAlg])) h.update(MP(clientDHPubKey)) h.update(MP(f)) h.update(sharedSecret) exchangeHash = h.digest() self.sendPacket(MSG_KEXDH_REPLY, NS(self.factory.publicKeys[self.keyAlg])+ \ MP(f)+NS(keys.signData(self.factory.privateKeys[self.keyAlg], exchangeHash))) self._keySetup(sharedSecret, exchangeHash) elif self.kexAlg == 'diffie-hellman-group-exchange-sha1': self.kexAlg = 'diffie-hellman-group-exchange-sha1-old' self.ideal = struct.unpack('>L', packet)[0] self.g, self.p = self.factory.getDHPrime(self.ideal) self.sendPacket(MSG_KEX_DH_GEX_GROUP, MP(self.p)+MP(self.g)) else: raise error.ConchError('bad kexalg: %s'%self.kexAlg)
def ssh_KEX_DH_GEX_REQUEST_OLD(self, packet): if self.ignoreNextPacket: self.ignoreNextPacket = 0 return if self.kexAlg == 'diffie-hellman-group1-sha1': # this is really KEXDH_INIT clientDHPubKey, foo = getMP(packet) y = Util.number.getRandomNumber(16, entropy.get_bytes) f = pow(DH_GENERATOR, y, DH_PRIME) sharedSecret = _MPpow(clientDHPubKey, y, DH_PRIME) h = sha.new() h.update(NS(self.otherVersionString)) h.update(NS(self.ourVersionString)) h.update(NS(self.clientKexInitPayload)) h.update(NS(self.ourKexInitPayload)) h.update(NS(self.factory.publicKeys[self.keyAlg])) h.update(MP(clientDHPubKey)) h.update(MP(f)) h.update(sharedSecret) exchangeHash = h.digest() self.sendPacket(MSG_KEXDH_REPLY, NS(self.factory.publicKeys[self.keyAlg])+ \ MP(f)+NS(keys.signData(self.factory.privateKeys[self.keyAlg], exchangeHash))) self._keySetup(sharedSecret, exchangeHash) elif self.kexAlg == 'diffie-hellman-group-exchange-sha1': self.kexAlg = 'diffie-hellman-group-exchange-sha1-old' self.ideal = struct.unpack('>L', packet)[0] self.g, self.p = self.factory.getDHPrime(self.ideal) self.sendPacket(MSG_KEX_DH_GEX_GROUP, MP(self.p) + MP(self.g)) else: raise error.ConchError('bad kexalg: %s' % self.kexAlg)
def ssh_KEX_DH_GEX_INIT(self, packet): clientDHPubKey, foo = getMP(packet) # if y < 1024, openssh will reject us: "bad server public DH value". # y<1024 means f will be short, and of the form 2^y, so an observer # could trivially derive our secret y from f. Openssh detects this # and complains, so avoid creating such values by requiring y to be # larger than ln2(self.p) # TODO: we should also look at the value they send to us and reject # insecure values of f (if g==2 and f has a single '1' bit while the # rest are '0's, then they must have used a small y also). # TODO: This could be computed when self.p is set up # or do as openssh does and scan f for a single '1' bit instead minimum = long(math.floor(math.log(self.p) / math.log(2)) + 1) tries = 0 pSize = Util.number.size(self.p) y = Util.number.getRandomNumber(pSize, entropy.get_bytes) while tries < 10 and y < minimum: tries += 1 y = Util.number.getRandomNumber(pSize, entropy.get_bytes) assert(y >= minimum) # TODO: test_conch just hangs if this is hit # the chance of it being hit are really really low f = pow(self.g, y, self.p) sharedSecret = _MPpow(clientDHPubKey, y, self.p) h = sha.new() h.update(NS(self.otherVersionString)) h.update(NS(self.ourVersionString)) h.update(NS(self.clientKexInitPayload)) h.update(NS(self.ourKexInitPayload)) h.update(NS(self.factory.publicKeys[self.keyAlg])) if self.kexAlg == 'diffie-hellman-group-exchange-sha1': h.update(struct.pack('>3L', self.min, self.ideal, self.max)) else: h.update(struct.pack('>L', self.ideal)) h.update(MP(self.p)) h.update(MP(self.g)) h.update(MP(clientDHPubKey)) h.update(MP(f)) h.update(sharedSecret) exchangeHash = h.digest() self.sendPacket(MSG_KEX_DH_GEX_REPLY, NS(self.factory.publicKeys[self.keyAlg])+ \ MP(f)+NS(keys.signData(self.factory.privateKeys[self.keyAlg], exchangeHash))) self._keySetup(sharedSecret, exchangeHash)
def ssh_KEX_DH_GEX_INIT(self, packet): clientDHPubKey, foo = getMP(packet) # if y < 1024, openssh will reject us: "bad server public DH value". # y<1024 means f will be short, and of the form 2^y, so an observer # could trivially derive our secret y from f. Openssh detects this # and complains, so avoid creating such values by requiring y to be # larger than ln2(self.p) # TODO: we should also look at the value they send to us and reject # insecure values of f (if g==2 and f has a single '1' bit while the # rest are '0's, then they must have used a small y also). # TODO: This could be computed when self.p is set up # or do as openssh does and scan f for a single '1' bit instead minimum = long(math.floor(math.log(self.p) / math.log(2)) + 1) tries = 0 pSize = Util.number.size(self.p) y = Util.number.getRandomNumber(pSize, entropy.get_bytes) while tries < 10 and y < minimum: tries += 1 y = Util.number.getRandomNumber(pSize, entropy.get_bytes) assert (y >= minimum) # TODO: test_conch just hangs if this is hit # the chance of it being hit are really really low f = pow(self.g, y, self.p) sharedSecret = _MPpow(clientDHPubKey, y, self.p) h = sha.new() h.update(NS(self.otherVersionString)) h.update(NS(self.ourVersionString)) h.update(NS(self.clientKexInitPayload)) h.update(NS(self.ourKexInitPayload)) h.update(NS(self.factory.publicKeys[self.keyAlg])) if self.kexAlg == 'diffie-hellman-group-exchange-sha1': h.update(struct.pack('>3L', self.min, self.ideal, self.max)) else: h.update(struct.pack('>L', self.ideal)) h.update(MP(self.p)) h.update(MP(self.g)) h.update(MP(clientDHPubKey)) h.update(MP(f)) h.update(sharedSecret) exchangeHash = h.digest() self.sendPacket(MSG_KEX_DH_GEX_REPLY, NS(self.factory.publicKeys[self.keyAlg])+ \ MP(f)+NS(keys.signData(self.factory.privateKeys[self.keyAlg], exchangeHash))) self._keySetup(sharedSecret, exchangeHash)
def _continueGEX_GROUP(self, ignored, pubKey, f, signature): serverKey = keys.getPublicKeyObject(pubKey) sharedSecret = _MPpow(f, self.x, DH_PRIME) h = sha.new() h.update(NS(self.ourVersionString)) h.update(NS(self.otherVersionString)) h.update(NS(self.ourKexInitPayload)) h.update(NS(self.serverKexInitPayload)) h.update(NS(pubKey)) h.update(MP(self.DHpubKey)) h.update(MP(f)) h.update(sharedSecret) exchangeHash = h.digest() if not keys.verifySignature(serverKey, signature, exchangeHash): self.sendDisconnect(DISCONNECT_KEY_EXCHANGE_FAILED, 'bad signature') return self._keySetup(sharedSecret, exchangeHash)