Skip to content

Commit f7a2150

Browse files
committed
fix: Extend SignerInfo to support getting in the alg enum
1 parent 423e82b commit f7a2150

File tree

2 files changed

+106
-1
lines changed

2 files changed

+106
-1
lines changed

src/c2pa/c2pa.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,49 @@ class C2paSignerInfo(ctypes.Structure):
205205
("ta_url", ctypes.c_char_p),
206206
]
207207

208+
# Mapping from C2paSigningAlg enum to string representation
209+
_ALG_MAPPING = {
210+
C2paSigningAlg.ES256: b"es256",
211+
C2paSigningAlg.ES384: b"es384",
212+
C2paSigningAlg.ES512: b"es512",
213+
C2paSigningAlg.PS256: b"ps256",
214+
C2paSigningAlg.PS384: b"ps384",
215+
C2paSigningAlg.PS512: b"ps512",
216+
C2paSigningAlg.ED25519: b"ed25519",
217+
}
218+
219+
def __init__(self, alg=None, sign_cert=None, private_key=None, ta_url=None):
220+
"""Initialize C2paSignerInfo with optional parameters.
221+
222+
Args:
223+
alg: The signing algorithm, either as a C2paSigningAlg enum or string or bytes
224+
(will be converted accordingly to bytes for native library use)
225+
sign_cert: The signing certificate as a string
226+
private_key: The private key as a string
227+
ta_url: The timestamp authority URL as bytes
228+
"""
229+
# Handle alg parameter - can be C2paSigningAlg enum or string
230+
if alg is not None:
231+
if isinstance(alg, C2paSigningAlg):
232+
# Convert enum to string representation
233+
alg_str = self._ALG_MAPPING.get(alg)
234+
if alg_str is None:
235+
raise ValueError(f"Unsupported signing algorithm: {alg}")
236+
alg = alg_str
237+
elif isinstance(alg, str):
238+
# Convert string to bytes
239+
alg = alg.encode('utf-8')
240+
elif isinstance(alg, bytes):
241+
# Already in bytes format
242+
pass
243+
else:
244+
raise TypeError(f"alg must be C2paSigningAlg enum, string, or bytes, got {type(alg)}")
245+
else:
246+
alg = None
247+
248+
# Call parent constructor with processed values
249+
super().__init__(alg, sign_cert, private_key, ta_url)
250+
208251

209252
class C2paReader(ctypes.Structure):
210253
"""Opaque structure for reader context."""

tests/test_unit_tests.py

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1391,7 +1391,69 @@ def test_read_file(self):
13911391
self.assertIn("manifests", file_data)
13921392
self.assertIn(expected_manifest_id, file_data["manifests"])
13931393

1394-
def test_sign_file(self):
1394+
def test_sign_file_alg_as_enum(self):
1395+
"""Test signing a file with C2PA manifest."""
1396+
# Set up test paths
1397+
temp_data_dir = os.path.join(self.data_dir, "temp_data")
1398+
os.makedirs(temp_data_dir, exist_ok=True)
1399+
output_path = os.path.join(temp_data_dir, "signed_output.jpg")
1400+
1401+
# Load test certificates and key
1402+
with open(os.path.join(self.data_dir, "es256_certs.pem"), "rb") as cert_file:
1403+
certs = cert_file.read()
1404+
with open(os.path.join(self.data_dir, "es256_private.key"), "rb") as key_file:
1405+
key = key_file.read()
1406+
1407+
# Create signer info
1408+
signer_info = C2paSignerInfo(
1409+
alg=SigningAlg.ES256,
1410+
sign_cert=certs,
1411+
private_key=key,
1412+
ta_url=b"http://timestamp.digicert.com"
1413+
)
1414+
1415+
# Create a simple manifest
1416+
manifest = {
1417+
"claim_generator": "python_internals_test",
1418+
"claim_generator_info": [{
1419+
"name": "python_internals_test",
1420+
"version": "0.0.1",
1421+
}],
1422+
"format": "image/jpeg",
1423+
"title": "Python Test Signed Image",
1424+
"ingredients": [],
1425+
"assertions": [
1426+
{
1427+
"label": "c2pa.actions",
1428+
"data": {
1429+
"actions": [
1430+
{
1431+
"action": "c2pa.opened"
1432+
}
1433+
]
1434+
}
1435+
}
1436+
]
1437+
}
1438+
1439+
# Convert manifest to JSON string
1440+
manifest_json = json.dumps(manifest)
1441+
1442+
try:
1443+
# Sign the file
1444+
result_json = sign_file(
1445+
self.testPath,
1446+
output_path,
1447+
manifest_json,
1448+
signer_info
1449+
)
1450+
1451+
finally:
1452+
# Clean up
1453+
if os.path.exists(output_path):
1454+
os.remove(output_path)
1455+
1456+
def test_sign_file_alg_as_bytes(self):
13951457
"""Test signing a file with C2PA manifest."""
13961458
# Set up test paths
13971459
temp_data_dir = os.path.join(self.data_dir, "temp_data")

0 commit comments

Comments
 (0)