1919import boto3
2020import base64
2121from flask_cors import CORS
22- from c2pa import *
23- from hashlib import sha256
22+ from c2pa import Builder , C2paSigningAlg , Signer
23+ from cryptography .hazmat .primitives import hashes , serialization
24+ from cryptography .hazmat .primitives .asymmetric import ec
25+ from cryptography .hazmat .backends import default_backend
2426
2527
2628# Load environment variable from .env file
4547# By default, env vars with the `FLASK_`` prefix
4648# app.config.from_prefixed_env()
4749
50+ # Declare global variables
51+ global private_key , kms , kms_key_id
52+
4853private_key = None
54+ kms = None
55+ kms_key_id = None
4956
5057if 'USE_LOCAL_KEYS' in app_config and app_config ['USE_LOCAL_KEYS' ] == 'True' :
5158 # local test certs for development (and test client)
5259 print ('Using local test certs for signing' )
5360
54- env_ps256_pem_path = os .environ .get ('PS256_PEM_PATH_PYTHON_EXAMPLE ' )
61+ env_es256_pem_path = os .environ .get ('ES256_PEM_PATH_PYTHON_EXAMPLE ' )
5562 env_cert_chain_path = os .environ .get ('CERT_CHAIN_PATH_PYTHON_EXAMPLE' )
56- ps256_pem_path = 'tests/test-certs/ps256.pem '
57- cert_chain_path = 'tests/test-certs/ps256.pub '
63+ es256_pem_path = 'tests/test-certs/es256_private.key '
64+ cert_chain_path = 'tests/test-certs/es256_certs.pem '
5865
59- if env_ps256_pem_path is not None and env_cert_chain_path is not None :
60- print (f"Using certificates pointed to by env variables { env_ps256_pem_path } and { env_cert_chain_path } " )
61- ps256_pem_path = env_ps256_pem_path
66+ if env_es256_pem_path is not None and env_cert_chain_path is not None :
67+ print (f"Using certificates pointed to by env variables { env_es256_pem_path } and { env_cert_chain_path } " )
68+ es256_pem_path = env_es256_pem_path
6269 cert_chain_path = env_cert_chain_path
63- elif os .path .exists (ps256_pem_path ) and os .path .exists (cert_chain_path ):
64- print (f"Using certificates added locally to this repo { ps256_pem_path } and { cert_chain_path } " )
70+ elif os .path .exists (es256_pem_path ) and os .path .exists (cert_chain_path ):
71+ print (f"Using certificates added locally to this repo { es256_pem_path } and { cert_chain_path } " )
6572 else :
6673 print ("Using provided default test certificates and certificate chain" )
67- ps256_pem_path = 'tests/certs/ps256.pem '
68- cert_chain_path = 'tests/certs/ps256.pub '
74+ es256_pem_path = 'tests/certs/es256_private.key '
75+ cert_chain_path = 'tests/certs/es256_certs.pem '
6976
70- private_key = open (ps256_pem_path , 'rb' ).read ()
77+ private_key = open (es256_pem_path , 'rb' ).read ()
7178 cert_chain = open (cert_chain_path , 'rb' ).read ()
7279
7380 encoded_cert_chain = base64 .b64encode (cert_chain ).decode ('utf-8' )
74- signing_alg_str = 'PS256 '
81+ signing_alg_str = 'ES256 '
7582else :
7683 print ('Using KMS for signing' )
7784
108115if 'TIMESTAMP_URL' in app_config and app_config ['TIMESTAMP_URL' ]:
109116 timestamp_url = app_config ['TIMESTAMP_URL' ]
110117else :
111- timestamp_url = 'http://timestamp.digicert.com' # Default timestamp URL (change to None later?)
118+ # Default timestamp URL (change to None later?)
119+ timestamp_url = 'http://timestamp.digicert.com'
112120
113121# TODO: Get signing_alg_str from env when we support more algorithms
114122try :
115- signing_alg = getattr (SigningAlg , signing_alg_str )
123+ signing_alg = getattr (C2paSigningAlg , signing_alg_str )
116124except AttributeError :
117125 raise ValueError (f"Unsupported signing algorithm: { signing_alg_str } " )
118126
119127
120128@app .route ("/attach" , methods = ["POST" ])
121- def resize ():
129+ def attach_sign_image ():
122130 """Gets a JPEG image to sign and returns the signed JPEG image"""
123131
124132 request_data = request .get_data ()
@@ -139,11 +147,12 @@ def resize():
139147 "data" : {
140148 "actions" : [
141149 {
142- "action" : "c2pa.edited " ,
150+ "action" : "c2pa.created " ,
143151 "softwareAgent" : {
144152 "name" : "C2PA Python Example" ,
145153 "version" : "0.1.0"
146- }
154+ },
155+ "digitalSourceType" : "http://cv.iptc.org/newscodes/digitalsourcetype/digitalCreation"
147156 }
148157 ]
149158 }
@@ -152,26 +161,45 @@ def resize():
152161 })
153162
154163 try :
155- builder = Builder (manifest )
156-
157- signer = create_signer (kms_sign , signing_alg ,
158- cert_chain , timestamp_url )
159-
160- result = io .BytesIO (b"" )
161- builder .sign (signer , content_type , io .BytesIO (request_data ), result )
162-
163- return result .getvalue ()
164+ with Builder (manifest ) as builder :
165+ # Create signer using the new API
166+ callback_func = es256_sign if private_key is not None else kms_sign
167+ signer = Signer .from_callback (
168+ callback = callback_func ,
169+ alg = signing_alg ,
170+ certs = cert_chain ,
171+ tsa_url = timestamp_url
172+ )
173+
174+ result = io .BytesIO (b"" )
175+ builder .sign (signer , content_type , io .BytesIO (request_data ), result )
176+
177+ return result .getvalue ()
164178 except Exception as e :
165179 logging .error (e )
166180 abort (500 , description = e )
167181
168182
183+ # Uses ES256 alg to sign
184+ def es256_sign (data : bytes ) -> bytes :
185+ """Signs the data using ES256 algorithm with the private key"""
186+ private_key_obj = serialization .load_pem_private_key (
187+ private_key ,
188+ password = None ,
189+ backend = default_backend ()
190+ )
191+ signature = private_key_obj .sign (
192+ data ,
193+ ec .ECDSA (hashes .SHA256 ())
194+ )
195+ return signature
196+
197+
169198# Uses KMS to sign
170199def kms_sign (data : bytes ) -> bytes :
171200 """Signs the data using a KMS key id"""
172-
173- hashed_data = sha256 (data ).digest ()
174- return kms .sign (KeyId = kms_key_id , Message = hashed_data , MessageType = "DIGEST" , SigningAlgorithm = "ECDSA_SHA_256" )["Signature" ]
201+ result = kms .sign (KeyId = kms_key_id , Message = data , MessageType = "RAW" , SigningAlgorithm = "ECDSA_SHA_256" )["Signature" ]
202+ return result
175203
176204
177205@app .route ("/health" , methods = ["GET" ])
@@ -208,8 +236,8 @@ def sign():
208236 try :
209237 data = request .get_data ()
210238 if private_key is not None :
211- print ('Using sign_ps256 ' )
212- return sign_ps256 (data , private_key )
239+ print ('Using es256_sign ' )
240+ return es256_sign (data )
213241 else :
214242 print ('Using kms_sign' )
215243 return kms_sign (data )
0 commit comments