KeyLock Class
Overview
The KeyLock
class encapsulates the ciphertext of a public-key encrypted symmetric block cipher key and its pertinent metadata, such as the public key used during encryption. Key locks are used in hybrid encryption schemes where a symmetric cipher encrypts the data and a public-key cipher encrypts the symmetric key.
Package: keychain.core.key_lock
from keychain.core.key_lock import KeyLock
Class Definition
class KeyLock(SerializableObject):
"""A key lock is the encapsulation of ciphertext of an encrypted symmetric key."""
Constructor
def __init__(
self,
serialized_string: Optional[bytes] = None,
serialization_format: SerializationFormat = SerializationFormat.PROTOBUF,
c_pointer: Optional[ctypes.c_void_p] = None,
) -> None
Initialize a KeyLock object.
Parameters:
-
serialized_string
(bytes
, optional) - Serialized key lock bytes to deserialize -
serialization_format
(SerializationFormat
, optional) - Format of the serialized data (defaults to PROTOBUF) -
c_pointer
(ctypes.c_void_p
, optional) - Existing C pointer to wrap
Example:
from keychain.core.key_lock import KeyLock
from keychain.constants import SerializationFormat
# Create from serialized data
key_lock_bytes = b"..." # Previously serialized key lock
key_lock = KeyLock(
serialized_string=key_lock_bytes,
serialization_format=SerializationFormat.PROTOBUF
)
# Create from existing C pointer (typically from library functions)
key_lock = KeyLock(c_pointer=existing_pointer)
Class Methods
from_copy()
@classmethod
def from_copy(cls, other: "KeyLock") -> "KeyLock"
Create a copy of a key lock.
Parameters:
-
other
(KeyLock
) - The key lock to copy
Returns: A new KeyLock
instance that is a deep copy
Example:
original_key_lock = get_key_lock()
copied_key_lock = KeyLock.from_copy(original_key_lock)
Instance Methods
copy()
def copy(self) -> "KeyLock"
Create a deep copy of this key lock.
Returns: A new KeyLock
instance that is a deep copy
serialize()
def serialize(self) -> bytes
Serialize the key lock.
Returns: Bytes serialization of the key lock in protobuf format
Example:
key_lock = get_key_lock()
serialized_data = key_lock.serialize()
# Can be stored or transmitted and later reconstructed
restored_key_lock = KeyLock(serialized_data)
Properties
Public Key Properties
Algorithm Properties
algorithm
@property
def algorithm(self) -> EncryptionScheme
Get the public-key encryption algorithm used to encrypt the symmetric key.
Returns: The EncryptionScheme
used for key encryption
Example:
key_lock = get_key_lock()
algorithm = key_lock.algorithm
print(f"Encryption algorithm: {algorithm.name}")
Comparison Methods
eq()
def __eq__(self, other: object) -> bool
Compare key locks for equality.
Parameters:
-
other
(KeyLock
) - The other key lock to compare
Returns: True
if key locks are equal, False
otherwise
Example:
key_lock1 = get_key_lock()
key_lock2 = key_lock1.copy()
if key_lock1 == key_lock2:
print("Key locks are identical")
Example: Working with Key Locks
from keychain.core.key_lock import KeyLock
from keychain.constants import EncryptionScheme
def analyze_key_lock(key_lock: KeyLock):
"""Analyze a key lock and display its properties."""
print("=== Key Lock Analysis ===")
# Basic properties
print(f"Data type: {key_lock.data_type().name}")
print(f"Version: {key_lock.version.name}")
# Encryption algorithm
algorithm = key_lock.algorithm
print(f"Encryption algorithm: {algorithm.name}")
print(f"Algorithm value: {algorithm.value}")
# Public key information
public_key = key_lock.public_key
print(f"Public key length: {len(public_key)} characters")
print(f"Public key (first 32 chars): {public_key[:32]}...")
# Hash values for verification
pub_key_hash = key_lock.public_key_hash
cipher_hash = key_lock.ciphertext_hash
print(f"Public key hash: {pub_key_hash[:16]}...")
print(f"Ciphertext hash: {cipher_hash[:16]}...")
# Encrypted data
cipher_text = key_lock.cipher_text
print(f"Ciphertext length: {len(cipher_text)} bytes")
def compare_key_locks(key_locks: list[KeyLock]):
"""Compare multiple key locks for analysis."""
if not key_locks:
print("No key locks to compare")
return
print("=== Key Lock Comparison ===")
# Algorithm distribution
algorithms = {}
for i, key_lock in enumerate(key_locks):
alg = key_lock.algorithm.name
if alg not in algorithms:
algorithms[alg] = []
algorithms[alg].append(i)
print("Algorithm distribution:")
for alg, indices in algorithms.items():
print(f" {alg}: {len(indices)} key locks (indices: {indices})")
# Version distribution
versions = {}
for i, key_lock in enumerate(key_locks):
ver = key_lock.version.name
if ver not in versions:
versions[ver] = []
versions[ver].append(i)
print("\\nVersion distribution:")
for ver, indices in versions.items():
print(f" {ver}: {len(indices)} key locks (indices: {indices})")
# Check for duplicates
unique_hashes = set()
duplicates = []
for i, key_lock in enumerate(key_locks):
cipher_hash = key_lock.ciphertext_hash
if cipher_hash in unique_hashes:
duplicates.append(i)
else:
unique_hashes.add(cipher_hash)
if duplicates:
print(f"\\nDuplicate key locks found at indices: {duplicates}")
else:
print("\\nNo duplicate key locks found")
def validate_key_lock_chain(key_locks: list[KeyLock]) -> bool:
"""Validate that key locks form a valid encryption chain."""
print("=== Key Lock Chain Validation ===")
if not key_locks:
print("Empty key lock chain")
return True
# Check that all use compatible algorithms
algorithms = set(kl.algorithm for kl in key_locks)
if len(algorithms) > 1:
print(f"Warning: Multiple algorithms in chain: {[a.name for a in algorithms]}")
# Check version consistency
versions = set(kl.version for kl in key_locks)
if len(versions) > 1:
print(f"Warning: Multiple versions in chain: {[v.name for v in versions]}")
# Validate each key lock
valid_count = 0
for i, key_lock in enumerate(key_locks):
try:
# Basic validation
_ = key_lock.public_key
_ = key_lock.cipher_text
_ = key_lock.ciphertext_hash
valid_count += 1
print(f"✓ Key lock {i}: Valid")
except Exception as e:
print(f"✗ Key lock {i}: Invalid - {e}")
is_valid = valid_count == len(key_locks)
print(f"\\nChain validation: {'✓ Valid' if is_valid else '✗ Invalid'}")
print(f"Valid key locks: {valid_count}/{len(key_locks)}")
return is_valid
def extract_key_lock_metadata(key_lock: KeyLock) -> dict:
"""Extract comprehensive metadata from a key lock."""
try:
return {
"algorithm": {
"name": key_lock.algorithm.name,
"value": key_lock.algorithm.value
},
"version": {
"name": key_lock.version.name,
"value": key_lock.version.value
},
"public_key": {
"length": len(key_lock.public_key),
"hash": key_lock.public_key_hash,
"preview": key_lock.public_key[:32] + "..."
},
"ciphertext": {
"length": len(key_lock.cipher_text),
"hash": key_lock.ciphertext_hash
},
"serialization": {
"size": len(key_lock.serialize()),
"data_type": key_lock.data_type().name
}
}
except Exception as e:
return {"error": str(e)}
# Usage examples
def key_lock_examples():
"""Demonstrate key lock usage."""
# Get key locks from some source (e.g., encrypted data)
key_locks = get_key_locks_from_encrypted_data()
if key_locks:
# Analyze first key lock
analyze_key_lock(key_locks[0])
# Compare multiple key locks
if len(key_locks) > 1:
compare_key_locks(key_locks)
# Validate the chain
validate_key_lock_chain(key_locks)
# Extract metadata
metadata = extract_key_lock_metadata(key_locks[0])
print(f"\\n=== Metadata ===")
for category, data in metadata.items():
if isinstance(data, dict):
print(f"{category}:")
for key, value in data.items():
print(f" {key}: {value}")
else:
print(f"{category}: {data}")
if __name__ == "__main__":
key_lock_examples()
Example: Key Lock Security Analysis
from keychain.core.key_lock import KeyLock
from keychain.constants import EncryptionScheme
class KeyLockSecurityAnalyzer:
"""Analyzer for key lock security properties."""
def __init__(self):
# Define security levels for different algorithms
self.algorithm_security = {
EncryptionScheme.ECIES_ECP_SECP256R1: "medium",
EncryptionScheme.ECIES_ECP_SECP384R1: "high",
EncryptionScheme.ECIES_ECP_SECP521R1: "ultra",
EncryptionScheme.RSA_OAEP_SHA_2048: "medium",
EncryptionScheme.RSA_OAEP_SHA_3072: "high",
EncryptionScheme.RSA_OAEP_SHA_4096: "ultra"
}
def analyze_algorithm_security(self, key_lock: KeyLock) -> dict:
"""Analyze the security level of the encryption algorithm."""
algorithm = key_lock.algorithm
security_level = self.algorithm_security.get(algorithm, "unknown")
analysis = {
"algorithm": algorithm.name,
"security_level": security_level,
"algorithm_class": self._get_algorithm_class(algorithm),
"key_size": self._estimate_key_size(algorithm),
"quantum_resistant": self._is_quantum_resistant(algorithm)
}
return analysis
def _get_algorithm_class(self, algorithm: EncryptionScheme) -> str:
"""Get the general class of the encryption algorithm."""
name = algorithm.name
if "ECIES" in name:
return "Elliptic Curve Integrated Encryption"
elif "RSA" in name:
return "RSA Encryption"
elif "DLIES" in name:
return "Discrete Logarithm Integrated Encryption"
elif "ELGAMAL" in name:
return "ElGamal Encryption"
else:
return "Unknown"
def _estimate_key_size(self, algorithm: EncryptionScheme) -> str:
"""Estimate the key size from the algorithm name."""
name = algorithm.name
if "256" in name:
return "256-bit"
elif "384" in name:
return "384-bit"
elif "521" in name:
return "521-bit"
elif "2048" in name:
return "2048-bit"
elif "3072" in name:
return "3072-bit"
elif "4096" in name:
return "4096-bit"
else:
return "Unknown"
def _is_quantum_resistant(self, algorithm: EncryptionScheme) -> bool:
"""Check if algorithm is considered quantum resistant."""
# Note: Currently no algorithms are truly quantum resistant
# This is for future post-quantum algorithms
return False
def generate_security_report(self, key_locks: list[KeyLock]) -> str:
"""Generate a comprehensive security report."""
if not key_locks:
return "No key locks to analyze"
report_lines = ["KEY LOCK SECURITY ANALYSIS", "=" * 30, ""]
# Overall statistics
total = len(key_locks)
security_counts = {"unknown": 0, "medium": 0, "high": 0, "ultra": 0}
algorithm_counts = {}
for key_lock in key_locks:
analysis = self.analyze_algorithm_security(key_lock)
security_level = analysis["security_level"]
algorithm = analysis["algorithm"]
security_counts[security_level] += 1
algorithm_counts[algorithm] = algorithm_counts.get(algorithm, 0) + 1
# Security level distribution
report_lines.append("Security Level Distribution:")
for level, count in security_counts.items():
if count > 0:
percentage = count / total * 100
report_lines.append(f" {level.title()}: {count} ({percentage:.1f}%)")
report_lines.append("")
# Algorithm distribution
report_lines.append("Algorithm Distribution:")
for algorithm, count in sorted(algorithm_counts.items()):
percentage = count / total * 100
report_lines.append(f" {algorithm}: {count} ({percentage:.1f}%)")
report_lines.append("")
# Security recommendations
report_lines.append("Security Recommendations:")
low_security = security_counts["unknown"] + security_counts.get("low", 0)
if low_security > 0:
report_lines.append(f" ⚠ {low_security} key locks use weak algorithms")
report_lines.append(" Consider upgrading to higher security algorithms")
if security_counts["ultra"] == total:
report_lines.append(" ✓ All key locks use ultra-high security algorithms")
elif security_counts["high"] + security_counts["ultra"] >= total * 0.8:
report_lines.append(" ✓ Most key locks use high security algorithms")
else:
report_lines.append(" ⚠ Consider using higher security algorithms")
# Quantum resistance
quantum_resistant = sum(1 for kl in key_locks
if self._is_quantum_resistant(kl.algorithm))
if quantum_resistant == 0:
report_lines.append(" ⚠ No quantum-resistant algorithms detected")
report_lines.append(" Consider post-quantum cryptography for future-proofing")
return "\\n".join(report_lines)
def recommend_algorithm_upgrade(self, key_lock: KeyLock) -> str:
"""Recommend algorithm upgrades for a key lock."""
current = key_lock.algorithm
current_security = self.algorithm_security.get(current, "unknown")
if current_security == "ultra":
return f"Current algorithm {current.name} is already ultra-high security"
# Recommend upgrades based on current algorithm class
if "ECIES" in current.name:
return f"Consider upgrading from {current.name} to ECIES_ECP_SECP521R1 for ultra security"
elif "RSA" in current.name:
return f"Consider upgrading from {current.name} to RSA_OAEP_SHA_4096 for ultra security"
else:
return f"Consider upgrading {current.name} to a higher security algorithm"
# Usage example
def security_analysis_example():
"""Demonstrate key lock security analysis."""
analyzer = KeyLockSecurityAnalyzer()
key_locks = get_key_locks_from_system()
if key_locks:
# Analyze individual key lock
first_analysis = analyzer.analyze_algorithm_security(key_locks[0])
print("First Key Lock Analysis:")
for key, value in first_analysis.items():
print(f" {key}: {value}")
# Generate security report
report = analyzer.generate_security_report(key_locks)
print(f"\\n{report}")
# Get upgrade recommendations
for i, key_lock in enumerate(key_locks[:3]): # First 3
recommendation = analyzer.recommend_algorithm_upgrade(key_lock)
print(f"\\nKey Lock {i} upgrade: {recommendation}")
if __name__ == "__main__":
security_analysis_example()
Error Handling
Key lock operations can raise various exceptions:
Example:
from keychain.exceptions import KeychainValidationError, KeychainSecurityError
try:
# Create key lock from serialized data
key_lock = KeyLock(serialized_data)
# Access properties
public_key = key_lock.public_key
cipher_text = key_lock.cipher_text
algorithm = key_lock.algorithm
# Verify integrity
cipher_hash = key_lock.ciphertext_hash
# Check algorithm security
if key_lock.algorithm.name.endswith("4096"):
print("High security algorithm detected")
except KeychainValidationError as e:
print(f"Validation error: {e}")
except KeychainSecurityError as e:
print(f"Security error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
See Also
-
VerifiableData Class - Uses key locks for encryption
-
Credential Class - May contain encrypted data with key locks
-
Constants and Enums - EncryptionScheme and Version enums
-
Exception Classes - Error handling