Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/otdf_python/ecc_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,16 @@ def get_ec_compressed_pubkey_size(curve_type: int) -> int:
def get_ecc_mode_as_byte(self) -> int:
# Most significant bit: use_ecdsa_binding, lower 3 bits: curve_mode
return ((1 if self.use_ecdsa_binding else 0) << 7) | (self.curve_mode & 0x07)

@staticmethod
def from_string(curve_str: str) -> "ECCMode":
"""Create ECCMode from curve string like 'secp256r1' or 'secp384r1'."""
curve_map = {
"secp256r1": 0,
"secp384r1": 1,
"secp521r1": 2,
}
curve_mode = curve_map.get(curve_str.lower())
if curve_mode is None:
raise ValueError(f"Unsupported curve string: '{curve_str}'")
return ECCMode(curve_mode, False)
27 changes: 22 additions & 5 deletions src/otdf_python/nanotdf.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import contextlib
import hashlib
import json
import secrets
Expand Down Expand Up @@ -265,7 +266,9 @@ def create_nano_tdf(
self, payload: bytes | BytesIO, output_stream: BinaryIO, config: NanoTDFConfig
) -> int:
"""
Creates a NanoTDF with the provided payload and writes it to the output stream.
Stream-based NanoTDF creation - writes encrypted payload to an output stream.

For convenience method that returns bytes, use create_nanotdf() instead.
Supports KAS key wrapping if KAS info with public key is provided in config.

Args:
Expand Down Expand Up @@ -321,7 +324,9 @@ def read_nano_tdf(
platform_url: str | None = None,
) -> None:
"""
Reads a NanoTDF and writes the payload to the output stream.
Stream-based NanoTDF decryption - writes decrypted payload to an output stream.

For convenience method that returns bytes, use read_nanotdf() instead.
Supports KAS key unwrapping if kas_private_key is provided in config.

Args:
Expand Down Expand Up @@ -388,7 +393,11 @@ def read_nano_tdf(
key = asym.decrypt(wrapped_key)
ciphertext = payload[3 : -(2 + wrapped_key_len)]
else:
key = config.get("key")
# No wrapped key - need symmetric key from config
key = None
if config and hasattr(config, "cipher") and isinstance(config.cipher, str):
with contextlib.suppress(ValueError):
key = bytes.fromhex(config.cipher)
if not key:
raise InvalidNanoTDFConfig("Missing decryption key in config.")
ciphertext = payload[3:-2]
Expand Down Expand Up @@ -440,7 +449,11 @@ def _handle_legacy_key_config(
return key, config

def create_nanotdf(self, data: bytes, config: dict | NanoTDFConfig) -> bytes:
"""Create a NanoTDF from input data using the provided configuration."""
"""
Convenience method - creates a NanoTDF and returns the encrypted bytes.

For stream-based version, use create_nano_tdf() instead.
"""
if len(data) > self.K_MAX_TDF_SIZE:
raise NanoTDFMaxSizeLimit("exceeds max size for nano tdf")

Expand Down Expand Up @@ -514,7 +527,11 @@ def _extract_key_for_reading(
def read_nanotdf(
self, nanotdf_bytes: bytes, config: dict | NanoTDFConfig | None = None
) -> bytes:
"""Read and decrypt a NanoTDF, returning the original plaintext data."""
"""
Convenience method - decrypts a NanoTDF and returns the plaintext bytes.

For stream-based version, use read_nano_tdf() instead.
"""
output = BytesIO()
from otdf_python.header import Header # Local import to avoid circular import

Expand Down
Loading
Loading