diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py index 1a1ace9..d2d50c5 100644 --- a/third_party/tlslite/tlslite/constants.py +++ b/third_party/tlslite/tlslite/constants.py @@ -54,6 +54,20 @@ class ExtensionType: # RFC 6066 / 4366 tack = 0xF300 supports_npn = 13172 channel_id = 30032 + +class HashAlgorithm: + none = 0 + md5 = 1 + sha1 = 2 + sha224 = 3 + sha256 = 4 + sha384 = 5 + +class SignatureAlgorithm: + anonymous = 0 + rsa = 1 + dsa = 2 + ecdsa = 3 class NameType: host_name = 0 @@ -144,30 +158,42 @@ class CipherSuite: TLS_RSA_WITH_RC4_128_MD5 = 0x0004 + TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016 + TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033 + TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039 + TLS_DH_ANON_WITH_AES_128_CBC_SHA = 0x0034 TLS_DH_ANON_WITH_AES_256_CBC_SHA = 0x003A TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067 + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B + tripleDESSuites = [] tripleDESSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) tripleDESSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) tripleDESSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA) + tripleDESSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) aes128Suites = [] aes128Suites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA) aes128Suites.append(TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA) + aes128Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA) aes128Suites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA) aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256) + aes128Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) aes256Suites = [] aes256Suites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA) aes256Suites.append(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA) aes256Suites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA) + aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA) aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256) + aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) rc4Suites = [] rc4Suites.append(TLS_RSA_WITH_RC4_128_SHA) @@ -184,12 +210,18 @@ class CipherSuite: shaSuites.append(TLS_RSA_WITH_AES_128_CBC_SHA) shaSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA) shaSuites.append(TLS_RSA_WITH_RC4_128_SHA) + shaSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) + shaSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA) + shaSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA) shaSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA) shaSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA) sha256Suites = [] sha256Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256) sha256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256) + sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) + sha256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) + md5Suites = [] md5Suites.append(TLS_RSA_WITH_RC4_128_MD5) @@ -198,6 +230,7 @@ class CipherSuite: def _filterSuites(suites, settings): macNames = settings.macNames cipherNames = settings.cipherNames + keyExchangeNames = settings.keyExchangeNames macSuites = [] if "sha" in macNames: macSuites += CipherSuite.shaSuites @@ -216,7 +249,20 @@ class CipherSuite: if "rc4" in cipherNames: cipherSuites += CipherSuite.rc4Suites - return [s for s in suites if s in macSuites and s in cipherSuites] + keyExchangeSuites = [] + if "rsa" in keyExchangeNames: + keyExchangeSuites += CipherSuite.certSuites + if "dhe_rsa" in keyExchangeNames: + keyExchangeSuites += CipherSuite.dheCertSuites + if "srp_sha" in keyExchangeNames: + keyExchangeSuites += CipherSuite.srpSuites + if "srp_sha_rsa" in keyExchangeNames: + keyExchangeSuites += CipherSuite.srpCertSuites + if "dh_anon" in keyExchangeNames: + keyExchangeSuites += CipherSuite.anonSuites + + return [s for s in suites if s in macSuites and + s in cipherSuites and s in keyExchangeSuites] srpSuites = [] srpSuites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA) @@ -250,12 +296,24 @@ class CipherSuite: certSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA) certSuites.append(TLS_RSA_WITH_RC4_128_SHA) certSuites.append(TLS_RSA_WITH_RC4_128_MD5) - certAllSuites = srpCertSuites + certSuites @staticmethod def getCertSuites(settings): return CipherSuite._filterSuites(CipherSuite.certSuites, settings) + dheCertSuites = [] + dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) + dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) + dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA) + dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA) + dheCertSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) + + @staticmethod + def getDheCertSuites(settings): + return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings) + + certAllSuites = srpCertSuites + certSuites + dheCertSuites + anonSuites = [] anonSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA) anonSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA) @@ -264,6 +322,8 @@ class CipherSuite: def getAnonSuites(settings): return CipherSuite._filterSuites(CipherSuite.anonSuites, settings) + dhAllSuites = dheCertSuites + anonSuites + @staticmethod def canonicalCipherName(ciphersuite): "Return the canonical name of the cipher whose number is provided." diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py index ee37c30..7998e2e 100644 --- a/third_party/tlslite/tlslite/handshakesettings.py +++ b/third_party/tlslite/tlslite/handshakesettings.py @@ -14,7 +14,9 @@ from .utils import cipherfactory # RC4 is preferred as faster in Python, works in SSL3, and immune to CBC # issues such as timing attacks CIPHER_NAMES = ["rc4", "aes256", "aes128", "3des"] -MAC_NAMES = ["sha", "sha256"] # "md5" is allowed +MAC_NAMES = ["sha", "sha256"] # Don't allow "md5" by default. +ALL_MAC_NAMES = ["sha", "sha256", "md5"] +KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"] CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"] CERTIFICATE_TYPES = ["x509"] @@ -101,6 +103,7 @@ class HandshakeSettings(object): self.maxKeySize = 8193 self.cipherNames = CIPHER_NAMES self.macNames = MAC_NAMES + self.keyExchangeNames = KEY_EXCHANGE_NAMES self.cipherImplementations = CIPHER_IMPLEMENTATIONS self.certificateTypes = CERTIFICATE_TYPES self.minVersion = (3,1) @@ -115,6 +118,7 @@ class HandshakeSettings(object): other.maxKeySize = self.maxKeySize other.cipherNames = self.cipherNames other.macNames = self.macNames + other.keyExchangeNames = self.keyExchangeNames other.cipherImplementations = self.cipherImplementations other.certificateTypes = self.certificateTypes other.minVersion = self.minVersion @@ -147,6 +151,12 @@ class HandshakeSettings(object): for s in other.cipherNames: if s not in CIPHER_NAMES: raise ValueError("Unknown cipher name: '%s'" % s) + for s in other.macNames: + if s not in ALL_MAC_NAMES: + raise ValueError("Unknown MAC name: '%s'" % s) + for s in other.keyExchangeNames: + if s not in KEY_EXCHANGE_NAMES: + raise ValueError("Unknown key exchange name: '%s'" % s) for s in other.cipherImplementations: if s not in CIPHER_IMPLEMENTATIONS: raise ValueError("Unknown cipher implementation: '%s'" % s) diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py index 9a8e5f6..8b77ee6 100644 --- a/third_party/tlslite/tlslite/messages.py +++ b/third_party/tlslite/tlslite/messages.py @@ -500,9 +500,10 @@ class CertificateRequest(HandshakeMsg): return self.postWrite(w) class ServerKeyExchange(HandshakeMsg): - def __init__(self, cipherSuite): + def __init__(self, cipherSuite, version): HandshakeMsg.__init__(self, HandshakeType.server_key_exchange) self.cipherSuite = cipherSuite + self.version = version self.srp_N = 0 self.srp_g = 0 self.srp_s = bytearray(0) @@ -542,31 +543,38 @@ class ServerKeyExchange(HandshakeMsg): p.stopLengthCheck() return self - def write(self): + def write_params(self): w = Writer() if self.cipherSuite in CipherSuite.srpAllSuites: w.addVarSeq(numberToByteArray(self.srp_N), 1, 2) w.addVarSeq(numberToByteArray(self.srp_g), 1, 2) w.addVarSeq(self.srp_s, 1, 1) w.addVarSeq(numberToByteArray(self.srp_B), 1, 2) - if self.cipherSuite in CipherSuite.srpCertSuites: - w.addVarSeq(self.signature, 1, 2) - elif self.cipherSuite in CipherSuite.anonSuites: + elif self.cipherSuite in CipherSuite.dhAllSuites: w.addVarSeq(numberToByteArray(self.dh_p), 1, 2) w.addVarSeq(numberToByteArray(self.dh_g), 1, 2) w.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2) - if self.cipherSuite in []: # TODO support for signed_params - w.addVarSeq(self.signature, 1, 2) + else: + assert(False) + return w.bytes + + def write(self): + w = Writer() + w.bytes += self.write_params() + if self.cipherSuite in CipherSuite.certAllSuites: + if self.version >= (3,3): + # TODO: Signature algorithm negotiation not supported. + w.add(HashAlgorithm.sha1, 1) + w.add(SignatureAlgorithm.rsa, 1) + w.addVarSeq(self.signature, 1, 2) return self.postWrite(w) def hash(self, clientRandom, serverRandom): - oldCipherSuite = self.cipherSuite - self.cipherSuite = None - try: - bytes = clientRandom + serverRandom + self.write()[4:] - return MD5(bytes) + SHA1(bytes) - finally: - self.cipherSuite = oldCipherSuite + bytes = clientRandom + serverRandom + self.write_params() + if self.version >= (3,3): + # TODO: Signature algorithm negotiation not supported. + return SHA1(bytes) + return MD5(bytes) + SHA1(bytes) class ServerHelloDone(HandshakeMsg): def __init__(self): @@ -616,7 +624,7 @@ class ClientKeyExchange(HandshakeMsg): p.getFixBytes(len(p.bytes)-p.index) else: raise AssertionError() - elif self.cipherSuite in CipherSuite.anonSuites: + elif self.cipherSuite in CipherSuite.dhAllSuites: self.dh_Yc = bytesToNumber(p.getVarBytes(2)) else: raise AssertionError() diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py index 5d508ed..f6d13d4 100644 --- a/third_party/tlslite/tlslite/tlsconnection.py +++ b/third_party/tlslite/tlslite/tlsconnection.py @@ -23,7 +23,109 @@ from .messages import * from .mathtls import * from .handshakesettings import HandshakeSettings from .utils.tackwrapper import * +from .utils.rsakey import RSAKey +class KeyExchange(object): + def __init__(self, cipherSuite, clientHello, serverHello, privateKey): + """ + Initializes the KeyExchange. privateKey is the signing private key. + """ + self.cipherSuite = cipherSuite + self.clientHello = clientHello + self.serverHello = serverHello + self.privateKey = privateKey + + def makeServerKeyExchange(): + """ + Returns a ServerKeyExchange object for the server's initial leg in the + handshake. If the key exchange method does not send ServerKeyExchange + (e.g. RSA), it returns None. + """ + raise NotImplementedError() + + def processClientKeyExchange(clientKeyExchange): + """ + Processes the client's ClientKeyExchange message and returns the + premaster secret. Raises TLSLocalAlert on error. + """ + raise NotImplementedError() + +class RSAKeyExchange(KeyExchange): + def makeServerKeyExchange(self): + return None + + def processClientKeyExchange(self, clientKeyExchange): + premasterSecret = self.privateKey.decrypt(\ + clientKeyExchange.encryptedPreMasterSecret) + + # On decryption failure randomize premaster secret to avoid + # Bleichenbacher's "million message" attack + randomPreMasterSecret = getRandomBytes(48) + if not premasterSecret: + premasterSecret = randomPreMasterSecret + elif len(premasterSecret)!=48: + premasterSecret = randomPreMasterSecret + else: + versionCheck = (premasterSecret[0], premasterSecret[1]) + if versionCheck != self.clientHello.client_version: + #Tolerate buggy IE clients + if versionCheck != self.serverHello.server_version: + premasterSecret = randomPreMasterSecret + return premasterSecret + +def _hexStringToNumber(s): + s = s.replace(" ", "").replace("\n", "") + if len(s) % 2 != 0: + raise ValueError("Length is not even") + return bytesToNumber(bytearray(s.decode("hex"))) + +class DHE_RSAKeyExchange(KeyExchange): + # 2048-bit MODP Group (RFC 3526, Section 3) + dh_p = _hexStringToNumber(""" +FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 +29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD +EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 +E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED +EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D +C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F +83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D +670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B +E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 +DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 +15728E5A 8AACAA68 FFFFFFFF FFFFFFFF""") + dh_g = 2 + + # RFC 3526, Section 8. + strength = 160 + + def makeServerKeyExchange(self): + # Per RFC 3526, Section 1, the exponent should have double the entropy + # of the strength of the curve. + self.dh_Xs = bytesToNumber(getRandomBytes(self.strength * 2 / 8)) + dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p) + + version = self.serverHello.server_version + serverKeyExchange = ServerKeyExchange(self.cipherSuite, version) + serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys) + hashBytes = serverKeyExchange.hash(self.clientHello.random, + self.serverHello.random) + if version >= (3,3): + # TODO: Signature algorithm negotiation not supported. + hashBytes = RSAKey.addPKCS1SHA1Prefix(hashBytes) + serverKeyExchange.signature = self.privateKey.sign(hashBytes) + return serverKeyExchange + + def processClientKeyExchange(self, clientKeyExchange): + dh_Yc = clientKeyExchange.dh_Yc + + # First half of RFC 2631, Section 2.1.5. Validate the client's public + # key. + if not 2 <= dh_Yc <= self.dh_p - 1: + raise TLSLocalAlert(AlertDescription.illegal_parameter, + "Invalid dh_Yc value") + + S = powMod(dh_Yc, self.dh_Xs, self.dh_p) + return numberToByteArray(S) class TLSConnection(TLSRecordLayer): """ @@ -500,6 +602,8 @@ class TLSConnection(TLSRecordLayer): if srpParams: cipherSuites += CipherSuite.getSrpAllSuites(settings) elif certParams: + # TODO: Client DHE_RSA not supported. + # cipherSuites += CipherSuite.getDheCertSuites(settings) cipherSuites += CipherSuite.getCertSuites(settings) elif anonParams: cipherSuites += CipherSuite.getAnonSuites(settings) @@ -1207,10 +1311,23 @@ class TLSConnection(TLSRecordLayer): else: break premasterSecret = result - # Perform the RSA key exchange - elif cipherSuite in CipherSuite.certSuites: + # Perform the RSA or DHE_RSA key exchange + elif (cipherSuite in CipherSuite.certSuites or + cipherSuite in CipherSuite.dheCertSuites): + if cipherSuite in CipherSuite.certSuites: + keyExchange = RSAKeyExchange(cipherSuite, + clientHello, + serverHello, + privateKey) + elif cipherSuite in CipherSuite.dheCertSuites: + keyExchange = DHE_RSAKeyExchange(cipherSuite, + clientHello, + serverHello, + privateKey) + else: + assert(False) for result in self._serverCertKeyExchange(clientHello, serverHello, - certChain, privateKey, + certChain, keyExchange, reqCert, reqCAs, cipherSuite, settings, ocspResponse): if result in (0,1): yield result @@ -1270,6 +1387,7 @@ class TLSConnection(TLSRecordLayer): CipherSuite.getSrpCertSuites(settings) cipherSuites += CipherSuite.getSrpSuites(settings) elif certChain: + cipherSuites += CipherSuite.getDheCertSuites(settings) cipherSuites += CipherSuite.getCertSuites(settings) elif anon: cipherSuites += CipherSuite.getAnonSuites(settings) @@ -1440,7 +1558,7 @@ class TLSConnection(TLSRecordLayer): B = (powMod(g, b, N) + (k*v)) % N #Create ServerKeyExchange, signing it if necessary - serverKeyExchange = ServerKeyExchange(cipherSuite) + serverKeyExchange = ServerKeyExchange(cipherSuite, self.version) serverKeyExchange.createSRP(N, g, s, B) if cipherSuite in CipherSuite.srpCertSuites: hashBytes = serverKeyExchange.hash(clientHello.random, @@ -1488,11 +1606,11 @@ class TLSConnection(TLSRecordLayer): def _serverCertKeyExchange(self, clientHello, serverHello, - serverCertChain, privateKey, + serverCertChain, keyExchange, reqCert, reqCAs, cipherSuite, settings, ocspResponse): - #Send ServerHello, Certificate[, CertificateRequest], - #ServerHelloDone + #Send ServerHello, Certificate[, ServerKeyExchange] + #[, CertificateRequest], ServerHelloDone msgs = [] # If we verify a client cert chain, return it @@ -1502,6 +1620,9 @@ class TLSConnection(TLSRecordLayer): msgs.append(Certificate(CertificateType.x509).create(serverCertChain)) if serverHello.status_request: msgs.append(CertificateStatus().create(ocspResponse)) + serverKeyExchange = keyExchange.makeServerKeyExchange() + if serverKeyExchange is not None: + msgs.append(serverKeyExchange) if reqCert and reqCAs: msgs.append(CertificateRequest().create(\ [ClientCertificateType.rsa_sign], reqCAs)) @@ -1560,21 +1681,13 @@ class TLSConnection(TLSRecordLayer): else: break clientKeyExchange = result - #Decrypt ClientKeyExchange - premasterSecret = privateKey.decrypt(\ - clientKeyExchange.encryptedPreMasterSecret) - - # On decryption failure randomize premaster secret to avoid - # Bleichenbacher's "million message" attack - randomPreMasterSecret = getRandomBytes(48) - versionCheck = (premasterSecret[0], premasterSecret[1]) - if not premasterSecret: - premasterSecret = randomPreMasterSecret - elif len(premasterSecret)!=48: - premasterSecret = randomPreMasterSecret - elif versionCheck != clientHello.client_version: - if versionCheck != self.version: #Tolerate buggy IE clients - premasterSecret = randomPreMasterSecret + #Process ClientKeyExchange + try: + premasterSecret = \ + keyExchange.processClientKeyExchange(clientKeyExchange) + except TLSLocalAlert, alert: + for result in self._sendError(alert.description, alert.message): + yield result #Get and check CertificateVerify, if relevant if clientCertChain: @@ -1622,7 +1735,7 @@ class TLSConnection(TLSRecordLayer): dh_Ys = powMod(dh_g, dh_Xs, dh_p) #Create ServerKeyExchange - serverKeyExchange = ServerKeyExchange(cipherSuite) + serverKeyExchange = ServerKeyExchange(cipherSuite, self.version) serverKeyExchange.createDH(dh_p, dh_g, dh_Ys) #Send ServerHello[, Certificate], ServerKeyExchange, diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite/tlslite/tlsrecordlayer.py index 01ff3e9..6ef3895 100644 --- a/third_party/tlslite/tlslite/tlsrecordlayer.py +++ b/third_party/tlslite/tlslite/tlsrecordlayer.py @@ -796,7 +796,8 @@ class TLSRecordLayer(object): elif subType == HandshakeType.certificate_verify: yield CertificateVerify().parse(p) elif subType == HandshakeType.server_key_exchange: - yield ServerKeyExchange(constructorType).parse(p) + yield ServerKeyExchange(constructorType, + self.version).parse(p) elif subType == HandshakeType.server_hello_done: yield ServerHelloDone().parse(p) elif subType == HandshakeType.client_key_exchange: diff --git a/third_party/tlslite/tlslite/utils/rsakey.py b/third_party/tlslite/tlslite/utils/rsakey.py index 3f2100e..fb022cc 100644 --- a/third_party/tlslite/tlslite/utils/rsakey.py +++ b/third_party/tlslite/tlslite/utils/rsakey.py @@ -60,7 +60,7 @@ class RSAKey(object): @return: A PKCS1-SHA1 signature on the passed-in data. """ hashBytes = SHA1(bytearray(bytes)) - prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes) + prefixedHashBytes = self.addPKCS1SHA1Prefix(hashBytes) sigBytes = self.sign(prefixedHashBytes) return sigBytes @@ -81,8 +81,8 @@ class RSAKey(object): hashBytes = SHA1(bytearray(bytes)) # Try it with/without the embedded NULL - prefixedHashBytes1 = self._addPKCS1SHA1Prefix(hashBytes, False) - prefixedHashBytes2 = self._addPKCS1SHA1Prefix(hashBytes, True) + prefixedHashBytes1 = self.addPKCS1SHA1Prefix(hashBytes, False) + prefixedHashBytes2 = self.addPKCS1SHA1Prefix(hashBytes, True) result1 = self.verify(sigBytes, prefixedHashBytes1) result2 = self.verify(sigBytes, prefixedHashBytes2) return (result1 or result2) @@ -221,7 +221,8 @@ class RSAKey(object): # Helper Functions for RSA Keys # ************************************************************************** - def _addPKCS1SHA1Prefix(self, bytes, withNULL=True): + @staticmethod + def addPKCS1SHA1Prefix(bytes, withNULL=True): # There is a long history of confusion over whether the SHA1 # algorithmIdentifier should be encoded with a NULL parameter or # with the parameter omitted. While the original intention was @@ -229,8 +230,7 @@ class RSAKey(object): # specifies the NULL should be included, and this behavior is also # mandated in recent versions of PKCS #1, and is what tlslite has # always implemented. Anyways, verification code should probably - # accept both. However, nothing uses this code yet, so this is - # all fairly moot. + # accept both. if not withNULL: prefixBytes = bytearray(\ [0x30,0x1f,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x04,0x14])