def generate(self, status): """Create a CertificateVerify message""" if self.msg_version is None: self.msg_version = status.version if self.sig_version is None: self.sig_version = self.msg_version if self.msg_alg is None and self.msg_version >= (3, 3): cert_req = next((msg for msg in status.handshake_messages[::-1] if isinstance(msg, CertificateRequest)), None) if cert_req is not None: self.msg_alg = next( (sig for sig in cert_req.supported_signature_algs if sig[1] == SignatureAlgorithm.rsa), None) if self.msg_alg is None: self.msg_alg = (HashAlgorithm.sha1, SignatureAlgorithm.rsa) if self.sig_alg is None: self.sig_alg = self.msg_alg # TODO: generate a random key if none provided if self.private_key is None: raise ValueError("Can't create a signature without private key!") verify_bytes = KeyExchange.calcVerifyBytes(self.sig_version, status.handshake_hashes, self.sig_alg, status.premaster_secret, status.client_random, status.server_random) signature = self.private_key.sign(verify_bytes) cert_verify = CertificateVerify(self.msg_version) cert_verify.create(signature, self.msg_alg) self.msg = cert_verify return cert_verify
def generate(self, status): """Create a CertificateVerify message""" if self.version is None: self.version = status.version if self.sig_type is None and self.version >= (3, 3): cert_req = next((msg for msg in status.handshake_messages[::-1] if isinstance(msg, CertificateRequest)), None) if cert_req is not None: self.sig_type = next((sig for sig in cert_req.supported_signature_algs if sig[1] == SignatureAlgorithm.rsa), None) if self.sig_type is None: self.sig_type = (HashAlgorithm.sha1, SignatureAlgorithm.rsa) # TODO: generate a random key if none provided if self.private_key is None: raise ValueError("Can't create a signature without private key!") verify_bytes = KeyExchange.calcVerifyBytes(status.version, status.handshake_hashes, self.sig_type, status.premaster_secret, status.client_random, status.server_random) signature = self.private_key.sign(verify_bytes) cert_verify = CertificateVerify(status.version) cert_verify.create(signature, self.sig_type) self.msg = cert_verify return cert_verify
def test_with_TLS1_1(self): vrfy = KeyExchange.calcVerifyBytes((3, 2), self.handshake_hashes, None, None, None, None) self.assertEqual(vrfy, bytearray( # MD5 hash b'\xe9\x9f\xb4\xd24\xe9\xf41S\xe6?\xa5\xfe\xad\x16\x14' # SHA1 hash b'L3\x81\xad\x1b\xc2\x14\xc0\x8e\xba\xe4\xb8\xa2\x9d(6V1\xfb\xb0' ))
def test_with_TLS1_1(self): vrfy = KeyExchange.calcVerifyBytes((3, 2), self.handshake_hashes, None, None, None, None) self.assertEqual(vrfy, bytearray( # MD5 hash b'\xe9\x9f\xb4\xd24\xe9\xf41S\xe6?\xa5\xfe\xad\x16\x14' # SHA1 hash b'L3\x81\xad\x1b\xc2\x14\xc0\x8e\xba\xe4\xb8\xa2\x9d(6V1\xfb\xb0' ))
def test_with_SSL3(self): vrfy = KeyExchange.calcVerifyBytes((3, 0), self.handshake_hashes, None, bytearray(b'\x04'*48), bytearray(b'\xaa'*32), bytearray(b'\xbb'*32)) self.assertEqual(vrfy, bytearray( b'r_\x06\xd2(\\}v\x87\xfc\xf5\xa2h\xd6S\xd8' b'\xed=\x9b\xe3\xd9_%qe\xa3k\xf5\x85\x0e?\x9fr\xfaML' ))
def test_with_SSL3(self): vrfy = KeyExchange.calcVerifyBytes((3, 0), self.handshake_hashes, None, bytearray(b'\x04'*48), bytearray(b'\xaa'*32), bytearray(b'\xbb'*32)) self.assertEqual(vrfy, bytearray( b'r_\x06\xd2(\\}v\x87\xfc\xf5\xa2h\xd6S\xd8' b'\xed=\x9b\xe3\xd9_%qe\xa3k\xf5\x85\x0e?\x9fr\xfaML' ))
def test_with_TLS1_2(self): vrfy = KeyExchange.calcVerifyBytes((3, 3), self.handshake_hashes, (HashAlgorithm.sha1, SignatureAlgorithm.rsa), None, None, None) self.assertEqual(vrfy, bytearray( # PKCS#1 prefix b'0!0\t\x06\x05+\x0e\x03\x02\x1a\x05\x00\x04\x14' # SHA1 hash b'L3\x81\xad\x1b\xc2\x14\xc0\x8e\xba\xe4\xb8\xa2\x9d(6V1\xfb\xb0'))
def test_with_TLS1_2(self): vrfy = KeyExchange.calcVerifyBytes((3, 3), self.handshake_hashes, (HashAlgorithm.sha1, SignatureAlgorithm.rsa), None, None, None) self.assertEqual(vrfy, bytearray( # PKCS#1 prefix b'0!0\t\x06\x05+\x0e\x03\x02\x1a\x05\x00\x04\x14' # SHA1 hash b'L3\x81\xad\x1b\xc2\x14\xc0\x8e\xba\xe4\xb8\xa2\x9d(6V1\xfb\xb0'))
def generate(self, status): """Create a CertificateVerify message.""" if self.msg_version is None: self.msg_version = status.version if self.sig_version is None: self.sig_version = self.msg_version if self.msg_alg is None and self.msg_version >= (3, 3): cert_req = next((msg for msg in status.handshake_messages[::-1] if isinstance(msg, CertificateRequest)), None) if cert_req is not None: self.msg_alg = next((sig for sig in cert_req.supported_signature_algs if sig[1] == SignatureAlgorithm.rsa or sig[0] == 8 and sig[1] in (4, 5, 6)), None) if self.msg_alg is None: self.msg_alg = (HashAlgorithm.sha1, SignatureAlgorithm.rsa) if self.sig_alg is None: self.sig_alg = self.msg_alg # TODO: generate a random key if none provided if self.signature is not None: signature = self.signature else: if self.private_key is None: raise ValueError("Can't create a signature without " "private key!") verify_bytes = KeyExchange.calcVerifyBytes(self.sig_version, status.handshake_hashes, self.sig_alg, status.premaster_secret, status.client_random, status.server_random) # we don't have to handle non pkcs1 padding because the # calcVerifyBytes does everything scheme = SignatureScheme.toRepr(self.sig_alg) hashName = None saltLen = 0 if scheme is None: padding = "pkcs1" else: padding = SignatureScheme.getPadding(scheme) if padding == 'pss': hashName = SignatureScheme.getHash(scheme) if self.rsa_pss_salt_len is None: self.rsa_pss_salt_len = \ getattr(hashlib, hashName)().digest_size def _newRawPrivateKeyOp(self, m, original_rawPrivateKeyOp, subs=None, xors=None): signBytes = numberToByteArray(m, numBytes(self.n)) signBytes = substitute_and_xor(signBytes, subs, xors) m = bytesToNumber(signBytes) # RSA operations are defined only on numbers that are smaller # than the modulus, so ensure the XORing or substitutions # didn't break it (especially necessary for pycrypto as # it raises exception in such case) if m > self.n: m %= self.n return original_rawPrivateKeyOp(m) oldPrivateKeyOp = self.private_key._rawPrivateKeyOp self.private_key._rawPrivateKeyOp = \ partial(_newRawPrivateKeyOp, self.private_key, original_rawPrivateKeyOp=oldPrivateKeyOp, subs=self.padding_subs, xors=self.padding_xors) try: signature = self.private_key.sign(verify_bytes, padding, hashName, self.rsa_pss_salt_len) finally: # make sure the changes are undone even if the signing fails self.private_key._rawPrivateKeyOp = oldPrivateKeyOp cert_verify = CertificateVerify(self.msg_version) cert_verify.create(signature, self.msg_alg) self.msg = cert_verify return cert_verify
def generate(self, status): """Create a CertificateVerify message.""" if self.msg_version is None: self.msg_version = status.version if self.sig_version is None: self.sig_version = self.msg_version if self.msg_alg is None and self.msg_version >= (3, 3): cert_req = next((msg for msg in status.handshake_messages[::-1] if isinstance(msg, CertificateRequest)), None) if cert_req is not None: self.msg_alg = next( (sig for sig in cert_req.supported_signature_algs if sig[1] == SignatureAlgorithm.rsa or sig[0] == 8 and sig[1] in (4, 5, 6)), None) if self.msg_alg is None: self.msg_alg = (HashAlgorithm.sha1, SignatureAlgorithm.rsa) if self.sig_alg is None: self.sig_alg = self.msg_alg # we need a copy of the handshake hashes for use in Extended Master # Secret calculation status.certificate_verify_handshake_hashes = \ status.handshake_hashes.copy() # TODO: generate a random key if none provided if self.signature is not None: signature = self.signature else: if self.private_key is None: raise ValueError("Can't create a signature without " "private key!") verify_bytes = KeyExchange.calcVerifyBytes(self.sig_version, status.handshake_hashes, self.sig_alg, status.premaster_secret, status.client_random, status.server_random) # we don't have to handle non pkcs1 padding because the # calcVerifyBytes does everything scheme = SignatureScheme.toRepr(self.sig_alg) hashName = None saltLen = 0 if scheme is None: padding = "pkcs1" else: padding = SignatureScheme.getPadding(scheme) if padding == 'pss': hashName = SignatureScheme.getHash(scheme) if self.rsa_pss_salt_len is None: self.rsa_pss_salt_len = \ getattr(hashlib, hashName)().digest_size def _newRawPrivateKeyOp(self, m, original_rawPrivateKeyOp, subs=None, xors=None): signBytes = numberToByteArray(m, numBytes(self.n)) signBytes = substitute_and_xor(signBytes, subs, xors) m = bytesToNumber(signBytes) return original_rawPrivateKeyOp(m) oldPrivateKeyOp = self.private_key._rawPrivateKeyOp self.private_key._rawPrivateKeyOp = \ partial(_newRawPrivateKeyOp, self.private_key, original_rawPrivateKeyOp=oldPrivateKeyOp, subs=self.padding_subs, xors=self.padding_xors) signature = self.private_key.sign(verify_bytes, padding, hashName, self.rsa_pss_salt_len) self.private_key._rawPrivateKeyOp = oldPrivateKeyOp cert_verify = CertificateVerify(self.msg_version) cert_verify.create(signature, self.msg_alg) self.msg = cert_verify return cert_verify