@@ -9,10 +9,262 @@ import TabItem from '@theme/TabItem';
99<Tabs groupId = " programming-lang" >
1010 <TabItem value = " python" label = " Python" default >
1111 This is how to sign a manifest using Python.
12+
13+ ``` python
14+ request_data = ... # This is the asset being signed
15+ content_type = ... # MIME type of the asset
16+
17+ manifest = json.dumps({
18+ " title" : " image.jpg" ,
19+ " format" : " image/jpeg" ,
20+ " claim_generator_info" : [
21+ {
22+ " name" : " Documentation example" ,
23+ " version" : " 0.0.1"
24+ }
25+ ],
26+ " assertions" : [
27+ {
28+ " label" : " c2pa.actions" ,
29+ " data" : {
30+ " actions" : [
31+ {
32+ " action" : " c2pa.edited" ,
33+ " softwareAgent" : {
34+ " name" : " C2PA Python Example" ,
35+ " version" : " 0.1.0"
36+ }
37+ }
38+ ]
39+ }
40+ }
41+ ]
42+ })
43+
44+ try :
45+ builder = Builder(manifest)
46+
47+ signer = create_signer(kms_sign, signing_alg,
48+ cert_chain, timestamp_url)
49+
50+ result = io.BytesIO(b " " )
51+ builder.sign(signer, content_type, io.BytesIO(request_data), result)
52+
53+ return result.getvalue()
54+ except Exception as e:
55+ logging.error(e)
56+ abort(500 , description = e)
57+ ```
58+
1259 </TabItem >
1360
1461<TabItem value = " node" label = " Node.js" >
1562 This is how to sign a manifest using Node.js.
63+
64+ Use the ` c2pa.sign() ` method to sign an ingredient, either locally if you have a signing certificate and key available, or by using a remote signing API.
65+
66+ ## Signing buffers
67+
68+ If you have an asset file's data loaded into memory, you can sign the the asset using the loaded buffer.
69+
70+ ** NOTE** : Signing using a buffer is currently supported only for ` image/jpeg ` and ` image/png ` data. For all other file types, use the [ file-based approach] ( #signing-files ) .
71+
72+ ``` ts
73+ import { readFile } from ' node:fs/promises' ;
74+ import { createC2pa , createTestSigner } from ' c2pa-node' ;
75+
76+ // read an asset into a buffer
77+ const buffer = await readFile (' to-be-signed.jpg' );
78+ const asset: Asset = { buffer , mimeType: ' image/jpeg' };
79+
80+ // build a manifest to use for signing
81+ const manifest = new ManifestBuilder (
82+ {
83+ claim_generator: ' my-app/1.0.0' ,
84+ format: ' image/jpeg' ,
85+ title: ' buffer_signer.jpg' ,
86+ assertions: [
87+ {
88+ label: ' c2pa.actions' ,
89+ data: {
90+ actions: [
91+ {
92+ action: ' c2pa.created' ,
93+ },
94+ ],
95+ },
96+ },
97+ {
98+ label: ' com.custom.my-assertion' ,
99+ data: {
100+ description: ' My custom test assertion' ,
101+ version: ' 1.0.0' ,
102+ },
103+ },
104+ ],
105+ },
106+ { vendor: ' cai' },
107+ );
108+
109+ // create a signing function
110+ async function sign(asset , manifest ) {
111+ const signer = await createTestSigner ();
112+ const c2pa = createC2pa ({
113+ signer ,
114+ });
115+
116+ const { signedAsset, signedManifest } = await c2pa .sign ({
117+ asset ,
118+ manifest ,
119+ });
120+ }
121+
122+ // sign
123+ await sign (asset , manifest );
124+ ```
125+
126+ ## Signing files
127+
128+ To avoid loading the entire asset into memory (or for file types other than JPEG and PNG that don't support in-memory signing), pass in the file path to the asset file to sign it; for example:
129+
130+ ``` ts
131+ import { resolve } from ' node:path' ;
132+ import { createC2pa , createTestSigner } from ' c2pa-node' ;
133+
134+ // get the asset full path
135+ const asset = {
136+ path: resolve (' to-be-signed.jpg' ),
137+ };
138+ // define a location where to place the signed asset
139+ const outputPath = resolve (' signed.jpg' );
140+
141+ // create a signing function
142+ async function sign(asset , manifest ) {
143+ const signer = await createTestSigner ();
144+ const c2pa = createC2pa ({
145+ signer ,
146+ });
147+
148+ const { signedAsset, signedManifest } = await c2pa .sign ({
149+ manifest ,
150+ asset ,
151+ options: {
152+ outputPath ,
153+ },
154+ });
155+ }
156+
157+ // build a manifest to use for signing
158+ const manifest = new ManifestBuilder (
159+ {
160+ claim_generator: ' my-app/1.0.0' ,
161+ format: ' image/jpeg' ,
162+ title: ' buffer_signer.jpg' ,
163+ assertions: [
164+ {
165+ label: ' c2pa.actions' ,
166+ data: {
167+ actions: [
168+ {
169+ action: ' c2pa.created' ,
170+ },
171+ ],
172+ },
173+ },
174+ {
175+ label: ' com.custom.my-assertion' ,
176+ data: {
177+ description: ' My custom test assertion' ,
178+ version: ' 1.0.0' ,
179+ },
180+ },
181+ ],
182+ },
183+ { vendor: ' cai' },
184+ );
185+
186+ // sign
187+ await sign (asset , manifest );
188+ ```
189+
190+ ## Remote signing
191+
192+ If you have access to a web service that performs signing, you can use it to sign remotely; for example:
193+
194+ ``` ts
195+ import { readFile } from ' node:fs/promises' ;
196+ import { fetch , Headers } from ' node-fetch' ;
197+ import { createC2pa , SigningAlgorithm } from ' c2pa-node' ;
198+
199+ function createRemoteSigner() {
200+ return {
201+ type: ' remote' ,
202+ async reserveSize() {
203+ const url = ` https://my.signing.service/box-size ` ;
204+ const res = await fetch (url );
205+ const data = (await res .json ()) as { boxSize: number };
206+ return data .boxSize ;
207+ },
208+ async sign({ reserveSize , toBeSigned }) {
209+ const url = ` https://my.signing.service/sign?boxSize=${reserveSize } ` ;
210+ const res = await fetch (url , {
211+ method: ' POST' ,
212+ headers: new Headers ({
213+ ' Content-Type' : ' application/octet-stream' ,
214+ }),
215+ body: toBeSigned ,
216+ });
217+ return res .buffer ();
218+ },
219+ };
220+ }
221+
222+ async function sign(asset , manifest ) {
223+ const signer = createRemoteSigner ();
224+ const c2pa = createC2pa ({
225+ signer ,
226+ });
227+
228+ const { signedAsset, signedManifest } = await c2pa .sign ({
229+ asset ,
230+ manifest ,
231+ });
232+ }
233+
234+ const buffer = await readFile (' to-be-signed.jpg' );
235+ const asset: Asset = { buffer , mimeType: ' image/jpeg' };
236+
237+ const manifest = new ManifestBuilder (
238+ {
239+ claim_generator: ' my-app/1.0.0' ,
240+ format: ' image/jpeg' ,
241+ title: ' buffer_signer.jpg' ,
242+ assertions: [
243+ {
244+ label: ' c2pa.actions' ,
245+ data: {
246+ actions: [
247+ {
248+ action: ' c2pa.created' ,
249+ },
250+ ],
251+ },
252+ },
253+ {
254+ label: ' com.custom.my-assertion' ,
255+ data: {
256+ description: ' My custom test assertion' ,
257+ version: ' 1.0.0' ,
258+ },
259+ },
260+ ],
261+ },
262+ { vendor: ' cai' },
263+ );
264+
265+ await sign (asset , manifest );
266+ ```
267+
16268</TabItem >
17269
18270<TabItem value = " cpp" label = " C++" >
0 commit comments