Package tlslite :: Module keyexchange
[hide private]
[frames] | no frames]

Source Code for Module tlslite.keyexchange

  1  # Authors: 
  2  #   Hubert Kario (2015) 
  3  # 
  4  # See the LICENSE file for legal information regarding use of this file. 
  5  """Handling of cryptographic operations for key exchange""" 
  6   
  7  from .mathtls import goodGroupParameters, makeK, makeU, makeX, \ 
  8          calcMasterSecret, paramStrength, RFC7919_GROUPS 
  9  from .errors import TLSInsufficientSecurity, TLSUnknownPSKIdentity, \ 
 10          TLSIllegalParameterException, TLSDecryptionFailed, TLSInternalError 
 11  from .messages import ServerKeyExchange, ClientKeyExchange, CertificateVerify 
 12  from .constants import SignatureAlgorithm, HashAlgorithm, CipherSuite, \ 
 13          ExtensionType, GroupName, ECCurveType, SignatureScheme 
 14  from .utils.ecc import decodeX962Point, encodeX962Point, getCurveByName, \ 
 15          getPointByteSize 
 16  from .utils.rsakey import RSAKey 
 17  from .utils.cryptomath import bytesToNumber, getRandomBytes, powMod, \ 
 18          numBits, numberToByteArray, divceil 
 19  from .utils.lists import getFirstMatching 
 20  from .utils import tlshashlib as hashlib 
 21  import ecdsa 
22 23 -class KeyExchange(object):
24 """ 25 Common API for calculating Premaster secret 26 27 NOT stable, will get moved from this file 28 """ 29
30 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey=None):
31 """Initialize KeyExchange. privateKey is the signing private key""" 32 self.cipherSuite = cipherSuite 33 self.clientHello = clientHello 34 self.serverHello = serverHello 35 self.privateKey = privateKey
36
37 - def makeServerKeyExchange(self, sigHash=None):
38 """ 39 Create a ServerKeyExchange object 40 41 Returns a ServerKeyExchange object for the server's initial leg in the 42 handshake. If the key exchange method does not send ServerKeyExchange 43 (e.g. RSA), it returns None. 44 """ 45 raise NotImplementedError()
46
47 - def makeClientKeyExchange(self):
48 """ 49 Create a ClientKeyExchange object 50 51 Returns a ClientKeyExchange for the second flight from client in the 52 handshake. 53 """ 54 return ClientKeyExchange(self.cipherSuite, 55 self.serverHello.server_version)
56
57 - def processClientKeyExchange(self, clientKeyExchange):
58 """ 59 Process ClientKeyExchange and return premaster secret 60 61 Processes the client's ClientKeyExchange message and returns the 62 premaster secret. Raises TLSLocalAlert on error. 63 """ 64 raise NotImplementedError()
65
66 - def processServerKeyExchange(self, srvPublicKey, 67 serverKeyExchange):
68 """Process the server KEX and return premaster secret""" 69 raise NotImplementedError()
70
71 - def _tls12_signSKE(self, serverKeyExchange, sigHash=None):
72 """Sign a TLSv1.2 SKE message.""" 73 try: 74 serverKeyExchange.hashAlg, serverKeyExchange.signAlg = \ 75 getattr(SignatureScheme, sigHash) 76 keyType = SignatureScheme.getKeyType(sigHash) 77 padType = SignatureScheme.getPadding(sigHash) 78 hashName = SignatureScheme.getHash(sigHash) 79 saltLen = getattr(hashlib, hashName)().digest_size 80 except AttributeError: 81 serverKeyExchange.signAlg = SignatureAlgorithm.rsa 82 serverKeyExchange.hashAlg = getattr(HashAlgorithm, sigHash) 83 keyType = 'rsa' 84 padType = 'pkcs1' 85 hashName = sigHash 86 saltLen = 0 87 88 assert keyType == 'rsa' 89 90 hashBytes = serverKeyExchange.hash(self.clientHello.random, 91 self.serverHello.random) 92 93 serverKeyExchange.signature = \ 94 self.privateKey.sign(hashBytes, 95 padding=padType, 96 hashAlg=hashName, 97 saltLen=saltLen) 98 99 if not serverKeyExchange.signature: 100 raise TLSInternalError("Empty signature") 101 102 if not self.privateKey.verify(serverKeyExchange.signature, 103 hashBytes, 104 padding=padType, 105 hashAlg=hashName, 106 saltLen=saltLen): 107 raise TLSInternalError("Server Key Exchange signature invalid")
108
109 - def signServerKeyExchange(self, serverKeyExchange, sigHash=None):
110 """ 111 Sign a server key exchange using default or specified algorithm 112 113 @type sigHash: str 114 @param sigHash: name of the signature hash to be used for signing 115 """ 116 if self.serverHello.server_version < (3, 3): 117 hashBytes = serverKeyExchange.hash(self.clientHello.random, 118 self.serverHello.random) 119 120 serverKeyExchange.signature = self.privateKey.sign(hashBytes) 121 122 if not serverKeyExchange.signature: 123 raise TLSInternalError("Empty signature") 124 125 if not self.privateKey.verify(serverKeyExchange.signature, 126 hashBytes): 127 raise TLSInternalError("Server Key Exchange signature invalid") 128 else: 129 self._tls12_signSKE(serverKeyExchange, sigHash)
130 131 @staticmethod
132 - def _tls12_verify_SKE(serverKeyExchange, publicKey, clientRandom, 133 serverRandom, validSigAlgs):
134 """Verify TLSv1.2 version of SKE.""" 135 if (serverKeyExchange.hashAlg, serverKeyExchange.signAlg) not in \ 136 validSigAlgs: 137 raise TLSIllegalParameterException("Server selected " 138 "invalid signature " 139 "algorithm") 140 schemeID = (serverKeyExchange.hashAlg, 141 serverKeyExchange.signAlg) 142 scheme = SignatureScheme.toRepr(schemeID) 143 if scheme is not None: 144 keyType = SignatureScheme.getKeyType(scheme) 145 padType = SignatureScheme.getPadding(scheme) 146 hashName = SignatureScheme.getHash(scheme) 147 saltLen = getattr(hashlib, hashName)().digest_size 148 else: 149 if serverKeyExchange.signAlg != SignatureAlgorithm.rsa: 150 raise TLSInternalError("non-RSA sigs are not supported") 151 keyType = 'rsa' 152 padType = 'pkcs1' 153 saltLen = 0 154 hashName = HashAlgorithm.toRepr(serverKeyExchange.hashAlg) 155 if hashName is None: 156 msg = "Unknown hash ID: {0}"\ 157 .format(serverKeyExchange.hashAlg) 158 raise TLSIllegalParameterException(msg) 159 assert keyType == 'rsa' 160 161 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom) 162 163 sigBytes = serverKeyExchange.signature 164 if not sigBytes: 165 raise TLSIllegalParameterException("Empty signature") 166 167 if not publicKey.verify(sigBytes, hashBytes, 168 padding=padType, 169 hashAlg=hashName, 170 saltLen=saltLen): 171 raise TLSDecryptionFailed("Server Key Exchange signature " 172 "invalid")
173 174 @staticmethod
175 - def verifyServerKeyExchange(serverKeyExchange, publicKey, clientRandom, 176 serverRandom, validSigAlgs):
177 """Verify signature on the Server Key Exchange message 178 179 the only acceptable signature algorithms are specified by validSigAlgs 180 """ 181 if serverKeyExchange.version < (3, 3): 182 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom) 183 sigBytes = serverKeyExchange.signature 184 185 if not sigBytes: 186 raise TLSIllegalParameterException("Empty signature") 187 188 if not publicKey.verify(sigBytes, hashBytes): 189 raise TLSDecryptionFailed("Server Key Exchange signature " 190 "invalid") 191 else: 192 KeyExchange._tls12_verify_SKE(serverKeyExchange, publicKey, 193 clientRandom, serverRandom, 194 validSigAlgs)
195 196 @staticmethod
197 - def calcVerifyBytes(version, handshakeHashes, signatureAlg, 198 premasterSecret, clientRandom, serverRandom):
199 """Calculate signed bytes for Certificate Verify""" 200 if version == (3, 0): 201 masterSecret = calcMasterSecret(version, 202 0, 203 premasterSecret, 204 clientRandom, 205 serverRandom) 206 verifyBytes = handshakeHashes.digestSSL(masterSecret, b"") 207 elif version in ((3, 1), (3, 2)): 208 verifyBytes = handshakeHashes.digest() 209 elif version == (3, 3): 210 scheme = SignatureScheme.toRepr(signatureAlg) 211 if scheme is None: 212 hashName = HashAlgorithm.toRepr(signatureAlg[0]) 213 padding = 'pkcs1' 214 else: 215 hashName = SignatureScheme.getHash(scheme) 216 padding = SignatureScheme.getPadding(scheme) 217 verifyBytes = handshakeHashes.digest(hashName) 218 if padding == 'pkcs1': 219 verifyBytes = RSAKey.addPKCS1Prefix(verifyBytes, hashName) 220 return verifyBytes
221 222 @staticmethod
223 - def makeCertificateVerify(version, handshakeHashes, validSigAlgs, 224 privateKey, certificateRequest, premasterSecret, 225 clientRandom, serverRandom):
226 """Create a Certificate Verify message 227 228 @param version: protocol version in use 229 @param handshakeHashes: the running hash of all handshake messages 230 @param validSigAlgs: acceptable signature algorithms for client side, 231 applicable only to TLSv1.2 (or later) 232 @param certificateRequest: the server provided Certificate Request 233 message 234 @param premasterSecret: the premaster secret, needed only for SSLv3 235 @param clientRandom: client provided random value, needed only for SSLv3 236 @param serverRandom: server provided random value, needed only for SSLv3 237 """ 238 signatureAlgorithm = None 239 # in TLS 1.2 we must decide which algorithm to use for signing 240 if version == (3, 3): 241 serverSigAlgs = certificateRequest.supported_signature_algs 242 signatureAlgorithm = getFirstMatching(validSigAlgs, serverSigAlgs) 243 # if none acceptable, do a last resort: 244 if signatureAlgorithm is None: 245 signatureAlgorithm = validSigAlgs[0] 246 verifyBytes = KeyExchange.calcVerifyBytes(version, handshakeHashes, 247 signatureAlgorithm, 248 premasterSecret, 249 clientRandom, 250 serverRandom) 251 scheme = SignatureScheme.toRepr(signatureAlgorithm) 252 # for pkcs1 signatures hash is used to add PKCS#1 prefix, but 253 # that was already done by calcVerifyBytes 254 hashName = None 255 saltLen = 0 256 if scheme is None: 257 padding = 'pkcs1' 258 else: 259 padding = SignatureScheme.getPadding(scheme) 260 if padding == 'pss': 261 hashName = SignatureScheme.getHash(scheme) 262 saltLen = getattr(hashlib, hashName)().digest_size 263 264 signedBytes = privateKey.sign(verifyBytes, 265 padding, 266 hashName, 267 saltLen) 268 if not privateKey.verify(signedBytes, verifyBytes, padding, hashName, 269 saltLen): 270 raise TLSInternalError("Certificate Verify signature invalid") 271 certificateVerify = CertificateVerify(version) 272 certificateVerify.create(signedBytes, signatureAlgorithm) 273 274 return certificateVerify
275
276 -class AuthenticatedKeyExchange(KeyExchange):
277 """ 278 Common methods for key exchanges that authenticate Server Key Exchange 279 280 Methods for signing Server Key Exchange message 281 """ 282
283 - def makeServerKeyExchange(self, sigHash=None):
284 """Prepare server side of key exchange with selected parameters""" 285 ske = super(AuthenticatedKeyExchange, self).makeServerKeyExchange() 286 self.signServerKeyExchange(ske, sigHash) 287 return ske
288
289 290 -class RSAKeyExchange(KeyExchange):
291 """ 292 Handling of RSA key exchange 293 294 NOT stable API, do NOT use 295 """ 296
297 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
298 super(RSAKeyExchange, self).__init__(cipherSuite, clientHello, 299 serverHello, privateKey) 300 self.encPremasterSecret = None
301
302 - def makeServerKeyExchange(self, sigHash=None):
303 """Don't create a server key exchange for RSA key exchange""" 304 return None
305
306 - def processClientKeyExchange(self, clientKeyExchange):
307 """Decrypt client key exchange, return premaster secret""" 308 premasterSecret = self.privateKey.decrypt(\ 309 clientKeyExchange.encryptedPreMasterSecret) 310 311 # On decryption failure randomize premaster secret to avoid 312 # Bleichenbacher's "million message" attack 313 randomPreMasterSecret = getRandomBytes(48) 314 if not premasterSecret: 315 premasterSecret = randomPreMasterSecret 316 elif len(premasterSecret) != 48: 317 premasterSecret = randomPreMasterSecret 318 else: 319 versionCheck = (premasterSecret[0], premasterSecret[1]) 320 if versionCheck != self.clientHello.client_version: 321 #Tolerate buggy IE clients 322 if versionCheck != self.serverHello.server_version: 323 premasterSecret = randomPreMasterSecret 324 return premasterSecret
325
326 - def processServerKeyExchange(self, srvPublicKey, 327 serverKeyExchange):
328 """Generate premaster secret for server""" 329 del serverKeyExchange # not present in RSA key exchange 330 premasterSecret = getRandomBytes(48) 331 premasterSecret[0] = self.clientHello.client_version[0] 332 premasterSecret[1] = self.clientHello.client_version[1] 333 334 self.encPremasterSecret = srvPublicKey.encrypt(premasterSecret) 335 return premasterSecret
336
337 - def makeClientKeyExchange(self):
338 """Return a client key exchange with clients key share""" 339 clientKeyExchange = super(RSAKeyExchange, self).makeClientKeyExchange() 340 clientKeyExchange.createRSA(self.encPremasterSecret) 341 return clientKeyExchange
342
343 344 -class ADHKeyExchange(KeyExchange):
345 """ 346 Handling of anonymous Diffie-Hellman Key exchange 347 348 FFDHE without signing serverKeyExchange useful for anonymous DH 349 """ 350
351 - def __init__(self, cipherSuite, clientHello, serverHello, 352 dhParams=None, dhGroups=None):
353 super(ADHKeyExchange, self).__init__(cipherSuite, clientHello, 354 serverHello) 355 #pylint: enable = invalid-name 356 self.dh_Xs = None 357 self.dh_Yc = None 358 if dhParams: 359 self.dh_g, self.dh_p = dhParams 360 else: 361 # 2048-bit MODP Group (RFC 5054, group 3) 362 self.dh_g, self.dh_p = goodGroupParameters[2] 363 self.dhGroups = dhGroups
364
365 - def makeServerKeyExchange(self):
366 """ 367 Prepare server side of anonymous key exchange with selected parameters 368 """ 369 # Check for RFC 7919 support 370 ext = self.clientHello.getExtension(ExtensionType.supported_groups) 371 if ext and self.dhGroups: 372 commonGroup = getFirstMatching(ext.groups, self.dhGroups) 373 if commonGroup: 374 self.dh_g, self.dh_p = RFC7919_GROUPS[commonGroup - 256] 375 elif getFirstMatching(ext.groups, range(256, 512)): 376 raise TLSInternalError("DHE key exchange attempted despite no " 377 "overlap between supported groups") 378 379 # Per RFC 3526, Section 1, the exponent should have double the entropy 380 # of the strength of the group. 381 randBytesNeeded = divceil(paramStrength(self.dh_p) * 2, 8) 382 self.dh_Xs = bytesToNumber(getRandomBytes(randBytesNeeded)) 383 dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p) 384 385 version = self.serverHello.server_version 386 serverKeyExchange = ServerKeyExchange(self.cipherSuite, version) 387 serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys) 388 # No sign for anonymous ServerKeyExchange. 389 return serverKeyExchange
390
391 - def processClientKeyExchange(self, clientKeyExchange):
392 """Use client provided parameters to establish premaster secret""" 393 dh_Yc = clientKeyExchange.dh_Yc 394 395 # First half of RFC 2631, Section 2.1.5. Validate the client's public 396 # key. 397 # use of safe primes also means that the p-1 is invalid 398 if not 2 <= dh_Yc < self.dh_p - 1: 399 raise TLSIllegalParameterException("Invalid dh_Yc value") 400 401 S = powMod(dh_Yc, self.dh_Xs, self.dh_p) 402 if S in (1, self.dh_p - 1): 403 raise TLSIllegalParameterException("Small subgroup capture") 404 return numberToByteArray(S)
405
406 - def processServerKeyExchange(self, srvPublicKey, serverKeyExchange):
407 """Process the server key exchange, return premaster secret.""" 408 del srvPublicKey 409 dh_p = serverKeyExchange.dh_p 410 # TODO make the minimum changeable 411 if dh_p < 2**1023: 412 raise TLSInsufficientSecurity("DH prime too small") 413 414 dh_g = serverKeyExchange.dh_g 415 if not 2 <= dh_g < dh_p - 1: 416 raise TLSIllegalParameterException("Invalid DH generator") 417 418 dh_Xc = bytesToNumber(getRandomBytes(32)) 419 dh_Ys = serverKeyExchange.dh_Ys 420 if not 2 <= dh_Ys < dh_p - 1: 421 raise TLSIllegalParameterException("Invalid server key share") 422 423 self.dh_Yc = powMod(dh_g, dh_Xc, dh_p) 424 if self.dh_Yc in (1, dh_p - 1): 425 raise TLSIllegalParameterException("Small subgroup capture") 426 427 S = powMod(dh_Ys, dh_Xc, dh_p) 428 if S in (1, dh_p - 1): 429 raise TLSIllegalParameterException("Small subgroup capture") 430 431 return numberToByteArray(S)
432
433 - def makeClientKeyExchange(self):
434 """Create client key share for the key exchange""" 435 cke = super(ADHKeyExchange, self).makeClientKeyExchange() 436 cke.createDH(self.dh_Yc) 437 return cke
438
439 440 # the DHE_RSA part comes from IETF ciphersuite names, we want to keep it 441 #pylint: disable = invalid-name 442 -class DHE_RSAKeyExchange(AuthenticatedKeyExchange, ADHKeyExchange):
443 """ 444 Handling of authenticated ephemeral Diffe-Hellman Key exchange. 445 """ 446
447 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey, 448 dhParams=None, dhGroups=None):
449 """ 450 Create helper object for Diffie-Hellamn key exchange. 451 452 @param dhParams: Diffie-Hellman parameters that will be used by 453 server. First element of the tuple is the generator, the second 454 is the prime. If not specified it will use a secure set (currently 455 a 2048-bit safe prime). 456 @type dhParams: 2-element tuple of int 457 """ 458 super(DHE_RSAKeyExchange, self).__init__(cipherSuite, clientHello, 459 serverHello, dhParams, 460 dhGroups) 461 #pylint: enable = invalid-name 462 self.privateKey = privateKey
463
464 465 -class AECDHKeyExchange(KeyExchange):
466 """ 467 Handling of anonymous Eliptic curve Diffie-Hellman Key exchange 468 469 ECDHE without signing serverKeyExchange useful for anonymous ECDH 470 """
471 - def __init__(self, cipherSuite, clientHello, serverHello, acceptedCurves):
472 super(AECDHKeyExchange, self).__init__(cipherSuite, clientHello, 473 serverHello) 474 self.ecdhXs = None 475 self.acceptedCurves = acceptedCurves 476 self.group_id = None 477 self.ecdhYc = None
478
479 - def makeServerKeyExchange(self, sigHash=None):
480 """Create AECDHE version of Server Key Exchange""" 481 #Get client supported groups 482 client_curves = self.clientHello.getExtension(\ 483 ExtensionType.supported_groups) 484 if client_curves is None: 485 # in case there is no extension, we can pick any curve, assume 486 # the most common 487 client_curves = [GroupName.secp256r1] 488 elif not client_curves.groups: 489 raise TLSInternalError("Can't do ECDHE with no client curves") 490 else: 491 client_curves = client_curves.groups 492 493 #Pick first client preferred group we support 494 self.group_id = getFirstMatching(client_curves, self.acceptedCurves) 495 if self.group_id is None: 496 raise TLSInsufficientSecurity("No mutual groups") 497 generator = getCurveByName(GroupName.toRepr(self.group_id)).generator 498 self.ecdhXs = ecdsa.util.randrange(generator.order()) 499 500 ecdhYs = encodeX962Point(generator * self.ecdhXs) 501 502 version = self.serverHello.server_version 503 serverKeyExchange = ServerKeyExchange(self.cipherSuite, version) 504 serverKeyExchange.createECDH(ECCurveType.named_curve, 505 named_curve=self.group_id, 506 point=ecdhYs) 507 # No sign for anonymous ServerKeyExchange 508 return serverKeyExchange
509
510 - def processClientKeyExchange(self, clientKeyExchange):
511 """Calculate premaster secret from previously generated SKE and CKE""" 512 curveName = GroupName.toRepr(self.group_id) 513 try: 514 ecdhYc = decodeX962Point(clientKeyExchange.ecdh_Yc, 515 getCurveByName(curveName)) 516 # TODO update python-ecdsa library to raise something more on point 517 except AssertionError: 518 raise TLSIllegalParameterException("Invalid ECC point") 519 520 sharedSecret = ecdhYc * self.ecdhXs 521 522 return numberToByteArray(sharedSecret.x(), getPointByteSize(ecdhYc))
523
524 - def processServerKeyExchange(self, srvPublicKey, serverKeyExchange):
525 """Process the server key exchange, return premaster secret""" 526 del srvPublicKey 527 528 if serverKeyExchange.curve_type != ECCurveType.named_curve \ 529 or serverKeyExchange.named_curve not in self.acceptedCurves: 530 raise TLSIllegalParameterException("Server picked curve we " 531 "didn't advertise") 532 533 curveName = GroupName.toStr(serverKeyExchange.named_curve) 534 curve = getCurveByName(curveName) 535 generator = curve.generator 536 537 ecdhXc = ecdsa.util.randrange(generator.order()) 538 ecdhYs = decodeX962Point(serverKeyExchange.ecdh_Ys, curve) 539 self.ecdhYc = encodeX962Point(generator * ecdhXc) 540 S = ecdhYs * ecdhXc 541 return numberToByteArray(S.x(), getPointByteSize(S))
542
543 - def makeClientKeyExchange(self):
544 """Make client key exchange for ECDHE""" 545 cke = super(AECDHKeyExchange, self).makeClientKeyExchange() 546 cke.createECDH(self.ecdhYc) 547 return cke
548
549 550 # The ECDHE_RSA part comes from the IETF names of ciphersuites, so we want to 551 # keep it 552 #pylint: disable = invalid-name 553 -class ECDHE_RSAKeyExchange(AuthenticatedKeyExchange, AECDHKeyExchange):
554 """Helper class for conducting ECDHE key exchange""" 555
556 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey, 557 acceptedCurves):
558 super(ECDHE_RSAKeyExchange, self).__init__(cipherSuite, clientHello, 559 serverHello, 560 acceptedCurves) 561 #pylint: enable = invalid-name 562 self.privateKey = privateKey
563
564 565 -class SRPKeyExchange(KeyExchange):
566 """Helper class for conducting SRP key exchange""" 567
568 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey, 569 verifierDB, srpUsername=None, password=None, settings=None):
570 """Link Key Exchange options with verifierDB for SRP""" 571 super(SRPKeyExchange, self).__init__(cipherSuite, clientHello, 572 serverHello, privateKey) 573 self.N = None 574 self.v = None 575 self.b = None 576 self.B = None 577 self.verifierDB = verifierDB 578 self.A = None 579 self.srpUsername = srpUsername 580 self.password = password 581 self.settings = settings 582 if srpUsername is not None and not isinstance(srpUsername, bytearray): 583 raise TypeError("srpUsername must be a bytearray object") 584 if password is not None and not isinstance(password, bytearray): 585 raise TypeError("password must be a bytearray object")
586
587 - def makeServerKeyExchange(self, sigHash=None):
588 """Create SRP version of Server Key Exchange""" 589 srpUsername = bytes(self.clientHello.srp_username) 590 #Get parameters from username 591 try: 592 entry = self.verifierDB[srpUsername] 593 except KeyError: 594 raise TLSUnknownPSKIdentity("Unknown identity") 595 (self.N, g, s, self.v) = entry 596 597 #Calculate server's ephemeral DH values (b, B) 598 self.b = bytesToNumber(getRandomBytes(32)) 599 k = makeK(self.N, g) 600 self.B = (powMod(g, self.b, self.N) + (k * self.v)) % self.N 601 602 #Create ServerKeyExchange, signing it if necessary 603 serverKeyExchange = ServerKeyExchange(self.cipherSuite, 604 self.serverHello.server_version) 605 serverKeyExchange.createSRP(self.N, g, s, self.B) 606 if self.cipherSuite in CipherSuite.srpCertSuites: 607 self.signServerKeyExchange(serverKeyExchange, sigHash) 608 return serverKeyExchange
609
610 - def processClientKeyExchange(self, clientKeyExchange):
611 """Calculate premaster secret from Client Key Exchange and sent SKE""" 612 A = clientKeyExchange.srp_A 613 if A % self.N == 0: 614 raise TLSIllegalParameterException("Invalid SRP A value") 615 616 #Calculate u 617 u = makeU(self.N, A, self.B) 618 619 #Calculate premaster secret 620 S = powMod((A * powMod(self.v, u, self.N)) % self.N, self.b, self.N) 621 return numberToByteArray(S)
622
623 - def processServerKeyExchange(self, srvPublicKey, serverKeyExchange):
624 """Calculate premaster secret from ServerKeyExchange""" 625 del srvPublicKey # irrelevant for SRP 626 N = serverKeyExchange.srp_N 627 g = serverKeyExchange.srp_g 628 s = serverKeyExchange.srp_s 629 B = serverKeyExchange.srp_B 630 631 if (g, N) not in goodGroupParameters: 632 raise TLSInsufficientSecurity("Unknown group parameters") 633 if numBits(N) < self.settings.minKeySize: 634 raise TLSInsufficientSecurity("N value is too small: {0}".\ 635 format(numBits(N))) 636 if numBits(N) > self.settings.maxKeySize: 637 raise TLSInsufficientSecurity("N value is too large: {0}".\ 638 format(numBits(N))) 639 if B % N == 0: 640 raise TLSIllegalParameterException("Suspicious B value") 641 642 #Client ephemeral value 643 a = bytesToNumber(getRandomBytes(32)) 644 self.A = powMod(g, a, N) 645 646 #Calculate client's static DH values (x, v) 647 x = makeX(s, self.srpUsername, self.password) 648 v = powMod(g, x, N) 649 650 #Calculate u 651 u = makeU(N, self.A, B) 652 653 #Calculate premaster secret 654 k = makeK(N, g) 655 S = powMod((B - (k*v)) % N, a+(u*x), N) 656 return numberToByteArray(S)
657
658 - def makeClientKeyExchange(self):
659 """Create ClientKeyExchange""" 660 cke = super(SRPKeyExchange, self).makeClientKeyExchange() 661 cke.createSRP(self.A) 662 return cke
663