Skip to content

Commit

Permalink
SNOW-1412405: fix ocsp validating sha384 signed certificate (#1951)
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-aling authored May 23, 2024
1 parent b05f25a commit 5e61c94
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 2 deletions.
5 changes: 5 additions & 0 deletions DESCRIPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne

- Added support for `token_file_path` connection parameter to read an OAuth token from a file when connecting to Snowflake.
- Added support for `debug_arrow_chunk` connection parameter to allow debugging raw arrow data in case of arrow data parsing failure.
- Fixed a bug that OCSP certificate signed using SHA384 algorithm cannot be verified.

- v3.10.1(May 21, 2024)

- Removed an incorrect error log message that could occur during arrow data conversion.

- v3.10.0(April 29,2024)

Expand Down
4 changes: 2 additions & 2 deletions src/snowflake/connector/ocsp_asn1crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ class SnowflakeOCSPAsn1Crypto(SnowflakeOCSP):
# map signature algorithm name to digest class
SIGNATURE_ALGORITHM_TO_DIGEST_CLASS = {
"sha256": hashes.SHA256,
"sha384": hashes.SHA3_384,
"sha512": hashes.SHA3_512,
"sha384": hashes.SHA384,
"sha512": hashes.SHA512,
}

def encode_cert_id_key(self, hkey):
Expand Down
73 changes: 73 additions & 0 deletions test/unit/test_ocsp.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from __future__ import annotations

import datetime
import logging
import os
import platform
Expand All @@ -13,6 +14,13 @@
from os import environ, path
from unittest import mock

from asn1crypto import x509 as asn1crypto509
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.serialization import Encoding

try:
from snowflake.connector.util_text import random_string
except ImportError:
Expand Down Expand Up @@ -546,3 +554,68 @@ def test_building_new_retry():
)

del os.environ["SF_OCSP_ACTIVATE_NEW_ENDPOINT"]


@pytest.mark.parametrize(
"hash_algorithm",
[
hashes.SHA256(),
hashes.SHA384(),
hashes.SHA512(),
hashes.SHA3_256(),
hashes.SHA3_384(),
hashes.SHA3_512(),
],
)
def test_signature_verification(hash_algorithm):
# Generate a private key
private_key = rsa.generate_private_key(
public_exponent=65537, key_size=1024, backend=default_backend()
)

# Generate a public key
public_key = private_key.public_key()

# Create a certificate
subject = x509.Name(
[
x509.NameAttribute(x509.NameOID.COUNTRY_NAME, "US"),
]
)

issuer = subject

cert = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(issuer)
.public_key(public_key)
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.datetime.now())
.not_valid_after(datetime.datetime.now() + datetime.timedelta(days=365))
.add_extension(
x509.SubjectAlternativeName([x509.DNSName("example.com")]),
critical=False,
)
.sign(private_key, hash_algorithm, default_backend())
)

# in snowflake, we use lib asn1crypto to load certificate, not using lib cryptography
asy1_509_cert = asn1crypto509.Certificate.load(cert.public_bytes(Encoding.DER))

# sha3 family is not recognized by asn1crypto library
if hash_algorithm.name.startswith("sha3-"):
with pytest.raises(ValueError):
SFOCSP().verify_signature(
asy1_509_cert.hash_algo,
cert.signature,
asy1_509_cert,
asy1_509_cert["tbs_certificate"],
)
else:
SFOCSP().verify_signature(
asy1_509_cert.hash_algo,
cert.signature,
asy1_509_cert,
asy1_509_cert["tbs_certificate"],
)

0 comments on commit 5e61c94

Please sign in to comment.