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 defaultCurve=GroupName.secp256r1):
473 super(AECDHKeyExchange, self).__init__(cipherSuite, clientHello, 474 serverHello) 475 self.ecdhXs = None 476 self.acceptedCurves = acceptedCurves 477 self.group_id = None 478 self.ecdhYc = None 479 self.defaultCurve = defaultCurve
480
481 - def makeServerKeyExchange(self, sigHash=None):
482 """Create AECDHE version of Server Key Exchange""" 483 #Get client supported groups 484 client_curves = self.clientHello.getExtension( 485 ExtensionType.supported_groups) 486 if client_curves is None: 487 # in case there is no extension, we can pick any curve, 488 # use the configured one 489 client_curves = [self.defaultCurve] 490 elif not client_curves.groups: 491 # extension should have been validated before 492 raise TLSInternalError("Can't do ECDHE with no client curves") 493 else: 494 client_curves = client_curves.groups 495 496 #Pick first client preferred group we support 497 self.group_id = getFirstMatching(client_curves, self.acceptedCurves) 498 if self.group_id is None: 499 raise TLSInsufficientSecurity("No mutual groups") 500 generator = getCurveByName(GroupName.toRepr(self.group_id)).generator 501 self.ecdhXs = ecdsa.util.randrange(generator.order()) 502 503 ecdhYs = encodeX962Point(generator * self.ecdhXs) 504 505 version = self.serverHello.server_version 506 serverKeyExchange = ServerKeyExchange(self.cipherSuite, version) 507 serverKeyExchange.createECDH(ECCurveType.named_curve, 508 named_curve=self.group_id, 509 point=ecdhYs) 510 # No sign for anonymous ServerKeyExchange 511 return serverKeyExchange
512
513 - def processClientKeyExchange(self, clientKeyExchange):
514 """Calculate premaster secret from previously generated SKE and CKE""" 515 curveName = GroupName.toRepr(self.group_id) 516 try: 517 ecdhYc = decodeX962Point(clientKeyExchange.ecdh_Yc, 518 getCurveByName(curveName)) 519 # TODO update python-ecdsa library to raise something more on point 520 except AssertionError: 521 raise TLSIllegalParameterException("Invalid ECC point") 522 523 sharedSecret = ecdhYc * self.ecdhXs 524 525 return numberToByteArray(sharedSecret.x(), getPointByteSize(ecdhYc))
526
527 - def processServerKeyExchange(self, srvPublicKey, serverKeyExchange):
528 """Process the server key exchange, return premaster secret""" 529 del srvPublicKey 530 531 if serverKeyExchange.curve_type != ECCurveType.named_curve \ 532 or serverKeyExchange.named_curve not in self.acceptedCurves: 533 raise TLSIllegalParameterException("Server picked curve we " 534 "didn't advertise") 535 536 curveName = GroupName.toStr(serverKeyExchange.named_curve) 537 curve = getCurveByName(curveName) 538 generator = curve.generator 539 540 ecdhXc = ecdsa.util.randrange(generator.order()) 541 ecdhYs = decodeX962Point(serverKeyExchange.ecdh_Ys, curve) 542 self.ecdhYc = encodeX962Point(generator * ecdhXc) 543 S = ecdhYs * ecdhXc 544 return numberToByteArray(S.x(), getPointByteSize(S))
545
546 - def makeClientKeyExchange(self):
547 """Make client key exchange for ECDHE""" 548 cke = super(AECDHKeyExchange, self).makeClientKeyExchange() 549 cke.createECDH(self.ecdhYc) 550 return cke
551
552 553 # The ECDHE_RSA part comes from the IETF names of ciphersuites, so we want to 554 # keep it 555 #pylint: disable = invalid-name 556 -class ECDHE_RSAKeyExchange(AuthenticatedKeyExchange, AECDHKeyExchange):
557 """Helper class for conducting ECDHE key exchange""" 558
559 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey, 560 acceptedCurves, defaultCurve=GroupName.secp256r1):
561 super(ECDHE_RSAKeyExchange, self).__init__(cipherSuite, clientHello, 562 serverHello, 563 acceptedCurves, 564 defaultCurve) 565 #pylint: enable = invalid-name 566 self.privateKey = privateKey
567
568 569 -class SRPKeyExchange(KeyExchange):
570 """Helper class for conducting SRP key exchange""" 571
572 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey, 573 verifierDB, srpUsername=None, password=None, settings=None):
574 """Link Key Exchange options with verifierDB for SRP""" 575 super(SRPKeyExchange, self).__init__(cipherSuite, clientHello, 576 serverHello, privateKey) 577 self.N = None 578 self.v = None 579 self.b = None 580 self.B = None 581 self.verifierDB = verifierDB 582 self.A = None 583 self.srpUsername = srpUsername 584 self.password = password 585 self.settings = settings 586 if srpUsername is not None and not isinstance(srpUsername, bytearray): 587 raise TypeError("srpUsername must be a bytearray object") 588 if password is not None and not isinstance(password, bytearray): 589 raise TypeError("password must be a bytearray object")
590
591 - def makeServerKeyExchange(self, sigHash=None):
592 """Create SRP version of Server Key Exchange""" 593 srpUsername = bytes(self.clientHello.srp_username) 594 #Get parameters from username 595 try: 596 entry = self.verifierDB[srpUsername] 597 except KeyError: 598 raise TLSUnknownPSKIdentity("Unknown identity") 599 (self.N, g, s, self.v) = entry 600 601 #Calculate server's ephemeral DH values (b, B) 602 self.b = bytesToNumber(getRandomBytes(32)) 603 k = makeK(self.N, g) 604 self.B = (powMod(g, self.b, self.N) + (k * self.v)) % self.N 605 606 #Create ServerKeyExchange, signing it if necessary 607 serverKeyExchange = ServerKeyExchange(self.cipherSuite, 608 self.serverHello.server_version) 609 serverKeyExchange.createSRP(self.N, g, s, self.B) 610 if self.cipherSuite in CipherSuite.srpCertSuites: 611 self.signServerKeyExchange(serverKeyExchange, sigHash) 612 return serverKeyExchange
613
614 - def processClientKeyExchange(self, clientKeyExchange):
615 """Calculate premaster secret from Client Key Exchange and sent SKE""" 616 A = clientKeyExchange.srp_A 617 if A % self.N == 0: 618 raise TLSIllegalParameterException("Invalid SRP A value") 619 620 #Calculate u 621 u = makeU(self.N, A, self.B) 622 623 #Calculate premaster secret 624 S = powMod((A * powMod(self.v, u, self.N)) % self.N, self.b, self.N) 625 return numberToByteArray(S)
626
627 - def processServerKeyExchange(self, srvPublicKey, serverKeyExchange):
628 """Calculate premaster secret from ServerKeyExchange""" 629 del srvPublicKey # irrelevant for SRP 630 N = serverKeyExchange.srp_N 631 g = serverKeyExchange.srp_g 632 s = serverKeyExchange.srp_s 633 B = serverKeyExchange.srp_B 634 635 if (g, N) not in goodGroupParameters: 636 raise TLSInsufficientSecurity("Unknown group parameters") 637 if numBits(N) < self.settings.minKeySize: 638 raise TLSInsufficientSecurity("N value is too small: {0}".\ 639 format(numBits(N))) 640 if numBits(N) > self.settings.maxKeySize: 641 raise TLSInsufficientSecurity("N value is too large: {0}".\ 642 format(numBits(N))) 643 if B % N == 0: 644 raise TLSIllegalParameterException("Suspicious B value") 645 646 #Client ephemeral value 647 a = bytesToNumber(getRandomBytes(32)) 648 self.A = powMod(g, a, N) 649 650 #Calculate client's static DH values (x, v) 651 x = makeX(s, self.srpUsername, self.password) 652 v = powMod(g, x, N) 653 654 #Calculate u 655 u = makeU(N, self.A, B) 656 657 #Calculate premaster secret 658 k = makeK(N, g) 659 S = powMod((B - (k*v)) % N, a+(u*x), N) 660 return numberToByteArray(S)
661
662 - def makeClientKeyExchange(self):
663 """Create ClientKeyExchange""" 664 cke = super(SRPKeyExchange, self).makeClientKeyExchange() 665 cke.createSRP(self.A) 666 return cke
667