@@ -73,10 +73,33 @@ def to_json(self) -> str:
7373
7474 @classmethod
7575 def from_dict (cls , data : dict ) -> HybridCertificate :
76- """
77- Create certificate from dictionary.
78- """
79- return cls (** data )
76+ """Create and validate a certificate from an untrusted dictionary."""
77+ expected_fields = set (cls .__dataclass_fields__ )
78+ provided_fields = set (data )
79+ if provided_fields != expected_fields :
80+ missing = sorted (expected_fields - provided_fields )
81+ unknown = sorted (provided_fields - expected_fields )
82+ raise ValueError (f"Invalid hybrid certificate fields: missing={ missing } , unknown={ unknown } " )
83+
84+ certificate = cls (** data )
85+ if certificate .version != 1 :
86+ raise ValueError ("Unsupported hybrid certificate version" )
87+ required_text = (
88+ certificate .serial_number ,
89+ certificate .subject ,
90+ certificate .issuer ,
91+ certificate .classical_algorithm ,
92+ certificate .classical_public_key_pem ,
93+ certificate .pqc_signature_algorithm ,
94+ certificate .pqc_public_key_b64 ,
95+ )
96+ if not all (isinstance (value , str ) and value .strip () for value in required_text ):
97+ raise ValueError ("Hybrid certificate contains an empty or invalid text field" )
98+
99+ certificate .pqc_public_key
100+ _parse_aware_datetime (certificate .not_before )
101+ _parse_aware_datetime (certificate .not_after )
102+ return certificate
80103
81104 @classmethod
82105 def from_json (cls , data : str ) -> HybridCertificate :
@@ -93,6 +116,16 @@ def pqc_public_key(self) -> bytes:
93116 return base64_to_bytes (self .pqc_public_key_b64 )
94117
95118
119+ def _parse_aware_datetime (value : str ) -> datetime :
120+ try :
121+ parsed = datetime .fromisoformat (value )
122+ except (TypeError , ValueError ) as exc :
123+ raise ValueError ("Invalid ISO-8601 certificate timestamp" ) from exc
124+ if parsed .tzinfo is None or parsed .utcoffset () is None :
125+ raise ValueError ("Certificate timestamps must include a timezone" )
126+ return parsed .astimezone (UTC )
127+
128+
96129def generate_hybrid_serial_number (prefix : str = "HYB" ) -> str :
97130 """
98131 Generate a random hybrid certificate serial number.
@@ -113,6 +146,9 @@ def create_unsigned_hybrid_certificate(
113146 """
114147 Create an unsigned hybrid certificate.
115148 """
149+ if not 1 <= days_valid <= 397 :
150+ raise ValueError ("days_valid must be between 1 and 397" )
151+
116152 now = datetime .now (UTC )
117153
118154 return HybridCertificate (
@@ -156,7 +192,10 @@ def is_hybrid_certificate_time_valid(certificate: HybridCertificate) -> bool:
156192 Verify hybrid certificate validity period.
157193 """
158194 now = datetime .now (UTC )
159- not_before = datetime .fromisoformat (certificate .not_before )
160- not_after = datetime .fromisoformat (certificate .not_after )
195+ try :
196+ not_before = _parse_aware_datetime (certificate .not_before )
197+ not_after = _parse_aware_datetime (certificate .not_after )
198+ except ValueError :
199+ return False
161200
162- return not_before <= now <= not_after
201+ return not_before <= not_after and not_before <= now <= not_after
0 commit comments