c2pa-c
C++ API for c2pa-c library
Loading...
Searching...
No Matches
c2pa.hpp
Go to the documentation of this file.
1// Copyright 2024 Adobe. All rights reserved.
2// This file is licensed to you under the Apache License,
3// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
4// or the MIT license (http://opensource.org/licenses/MIT),
5// at your option.
6// Unless required by applicable law or agreed to in writing,
7// this software is distributed on an "AS IS" BASIS, WITHOUT
8// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
9// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
10// specific language governing permissions and limitations under
11// each license.
12
13/// @file c2pa.hpp
14/// @brief C++ wrapper for the C2PA C library.
15/// @details This is used for creating and verifying C2PA manifests.
16/// This is an early version, and has not been fully tested.
17/// Thread safety is not guaranteed due to the use of errno and etc.
18
19#ifndef C2PA_H
20#define C2PA_H
21
22// Suppress unused function warning for GCC/Clang
23#ifdef __GNUC__
24#pragma GCC diagnostic push
25#pragma GCC diagnostic ignored "-Wunused-function"
26#endif
27
28// Suppress unused function warning for MSVC
29#ifdef _MSC_VER
30#pragma warning(push)
31#pragma warning(disable : 4505)
32#endif
33
34#include <filesystem>
35#include <fstream>
36#include <iostream>
37#include <string>
38#include <vector>
39#include <optional>
40
41#include <c2pa.h>
42
43using path = std::filesystem::path;
44
45// NOOP for now, can use later to define static library
46#define C2PA_CPP_API
47
48namespace c2pa
49{
50 using namespace std;
51
52 typedef C2paSignerInfo SignerInfo;
53
54 /// C2paException class for C2pa errors.
55 /// This class is used to throw exceptions for errors encountered by the C2pa library via c2pa_error().
56 class C2PA_CPP_API C2paException : public exception
57 {
58 private:
59 string message;
60
61 public:
63
64 C2paException(string what);
65
66 virtual const char *what() const noexcept;
67 };
68
69 /// Returns the version of the C2pa library.
70 string C2PA_CPP_API version();
71
72 /// Loads C2PA settings from a string in a given format.
73 /// @param data the string to load.
74 /// @param format the mime format of the string.
75 /// @throws a C2pa::C2paException for errors encountered by the C2PA library.
76 void C2PA_CPP_API load_settings(const string& data, const string& format);
77
78 /// Reads a file and returns the manifest json as a C2pa::String.
79 /// @param source_path the path to the file to read.
80 /// @param data_dir the directory to store binary resources (optional).
81 /// @return a string containing the manifest json if a manifest was found.
82 /// @throws a C2pa::C2paException for errors encountered by the C2PA library.
83 optional<string> C2PA_CPP_API read_file(const filesystem::path &source_path, const optional<path> data_dir = nullopt);
84
85 /// Reads a file and returns an ingredient JSON as a C2pa::String.
86 /// @param source_path the path to the file to read.
87 /// @param data_dir the directory to store binary resources.
88 /// @return a string containing the ingredient json.
89 /// @throws a C2pa::C2paException for errors encountered by the C2PA library.
90 std::string C2PA_CPP_API read_ingredient_file(const path &source_path, const path &data_dir);
91
92 /// Adds the manifest and signs a file.
93 /// @param source_path the path to the asset to be signed.
94 /// @param dest_path the path to write the signed file to.
95 /// @param manifest the manifest json to add to the file.
96 /// @param signer_info the signer info to use for signing.
97 /// @param data_dir the directory to store binary resources (optional).
98 /// @throws a C2pa::C2paException for errors encountered by the C2PA library.
99 void C2PA_CPP_API sign_file(const path &source_path,
100 const path &dest_path,
101 const char *manifest,
102 SignerInfo *signer_info,
103 const std::optional<path> data_dir = std::nullopt);
104
105 /// @brief Istream Class wrapper for C2paStream.
106 /// @details This class is used to wrap an input stream for use with the C2PA library.
107 class C2PA_CPP_API CppIStream : public C2paStream
108 {
109 public:
110 C2paStream *c_stream;
111 template <typename IStream>
112 explicit CppIStream(IStream &istream) {
113 static_assert(std::is_base_of<std::istream, IStream>::value,
114 "Stream must be derived from std::istream");
115 c_stream = c2pa_create_stream(reinterpret_cast<StreamContext *>(&istream), reader, seeker, writer, flusher);
116 }
117
118 CppIStream(const CppIStream &) = delete;
119 CppIStream &operator=(const CppIStream &) = delete;
120 CppIStream(CppIStream &&) = delete;
122
124
125 private:
126 static intptr_t reader(StreamContext *context, uint8_t *buffer, intptr_t size);
127 static intptr_t writer(StreamContext *context, const uint8_t *buffer, intptr_t size);
128 static intptr_t seeker(StreamContext *context, intptr_t offset, C2paSeekMode whence);
129 static intptr_t flusher(StreamContext *context);
130
131 friend class Reader;
132 };
133
134 /// @brief Ostream Class wrapper for C2paStream.
135 /// @details This class is used to wrap an output stream for use with the C2PA library.
136 class C2PA_CPP_API CppOStream : public C2paStream
137 {
138 public:
139 C2paStream *c_stream;
140 template <typename OStream>
141 explicit CppOStream(OStream &ostream) {
142 static_assert(std::is_base_of<std::ostream, OStream>::value, "Stream must be derived from std::ostream");
143 c_stream = c2pa_create_stream(reinterpret_cast<StreamContext *>(&ostream), reader, seeker, writer, flusher);
144 }
145
147
148 private:
149 static intptr_t reader(StreamContext *context, uint8_t *buffer, intptr_t size);
150 static intptr_t writer(StreamContext *context, const uint8_t *buffer, intptr_t size);
151 static intptr_t seeker(StreamContext *context, intptr_t offset, C2paSeekMode whence);
152 static intptr_t flusher(StreamContext *context);
153 };
154
155 /// @brief IOStream Class wrapper for C2paStream.
156 /// @details This class is used to wrap an input/output stream for use with the C2PA library.
157 class C2PA_CPP_API CppIOStream : public C2paStream
158 {
159 public:
160 C2paStream *c_stream;
161 template <typename IOStream>
162 CppIOStream(IOStream &iostream) {
163 static_assert(std::is_base_of<std::iostream, IOStream>::value, "Stream must be derived from std::iostream");
164 c_stream = c2pa_create_stream(reinterpret_cast<StreamContext *>(&iostream), reader, seeker, writer, flusher);
165 }
167
168 private:
169 static intptr_t reader(StreamContext *context, uint8_t *buffer, intptr_t size);
170 static intptr_t writer(StreamContext *context, const uint8_t *buffer, intptr_t size);
171 static intptr_t seeker(StreamContext *context, intptr_t offset, C2paSeekMode whence);
172 static intptr_t flusher(StreamContext *context);
173 };
174
175 /// @brief Reader class for reading a manifest.
176 /// @details This class is used to read and validate a manifest from a stream or file.
178 {
179 private:
180 C2paReader *c2pa_reader;
181 CppIStream *cpp_stream = NULL;
182
183 public:
184 /// @brief Create a Reader from a stream.
185 /// @details The validation_status field in the json contains validation results.
186 /// @param format The mime format of the stream.
187 /// @param stream The input stream to read from.
188 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
189 Reader(const std::string &format, std::istream &stream);
190
191 /// @brief Create a Reader from a file path.
192 /// @param source_path the path to the file to read.
193 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
194 Reader(const std::filesystem::path &source_path);
196
197 /// @brief Returns if the reader was created from an embedded manifest.
198 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
199 [[nodiscard]] inline bool is_embedded() const {
200 return c2pa_reader_is_embedded(c2pa_reader);
201 }
202
203 /// @brief Returns the remote url of the manifest if this `Reader`
204 /// obtained the manifest remotely.
205 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
206 [[nodiscard]] std::optional<std::string> remote_url() const;
207
208 /// @brief Get the manifest as a json string.
209 /// @return The manifest as a json string.
210 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
211 string json();
212
213 /// @brief Get a resource from the reader and write it to a file.
214 /// @param uri The uri of the resource.
215 /// @param path The path to write the resource to.
216 /// @return The number of bytes written.
217 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
218 int64_t get_resource(const string &uri, const std::filesystem::path &path);
219
220 /// @brief Get a resource from the reader and write it to an output stream.
221 /// @param uri The uri of the resource.
222 /// @param stream The output stream to write the resource to.
223 /// @return The number of bytes written.
224 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
225 int64_t get_resource(const string &uri, std::ostream &stream);
226
227 /// @brief Get the raw C2paReader pointer.
228 /// @return The raw C2paReader pointer.
229 /// @note This is intended for internal API use and compatibility with C APIs.
230 C2paReader* get_api_internal_raw_reader() const { return c2pa_reader; }
231
232 /// @brief Returns a vector of mime types that the SDK is able to
233 /// read manifests from.
234 static std::vector<std::string> supported_mime_types();
235 };
236
237 /// @brief Signer Callback function type.
238 /// @param data the data to sign.
239 /// @return the signature as a vector of bytes.
240 /// @details This function type is used to create a callback function for signing.
241 using SignerFunc = std::vector<unsigned char>(const std::vector<unsigned char> &);
242
243 /// @brief Signer class for creating a signer.
244 /// @details This class is used to create a signer from a signing algorithm, certificate, and TSA URI.
246 {
247 private:
248 C2paSigner *signer;
249
250 public:
251 /// @brief Create a Signer from a callback function, signing algorithm, certificate, and TSA URI.
252 /// @param callback the callback function to use for signing.
253 /// @param alg The signing algorithm to use.
254 /// @param sign_cert The certificate to use for signing.
255 /// @param tsa_uri The TSA URI to use for time-stamping.
256 Signer(SignerFunc *callback, C2paSigningAlg alg, const string &sign_cert, const string &tsa_uri);
257
258 Signer(C2paSigner *signer) : signer(signer) {}
259
260 Signer(const string &alg, const string &sign_cert, const string&private_key, const string &tsa_uri = NULL);
261
263
264 /// @brief Get the size to reserve for a signature for this signer.
265 /// @return Reserved size for the signature.
266 uintptr_t reserve_size();
267
268 /// @brief Get the C2paSigner
269 C2paSigner *c2pa_signer();
270 };
271
272 /// @brief Builder class for creating a manifest.
273 /// @details This class is used to create a manifest from a json string and add resources and ingredients to the manifest.
275 {
276 private:
277 C2paBuilder *builder;
278
279 public:
280 /// @brief Create a Builder from a manifest JSON string.
281 /// @param manifest_json The manifest JSON string.
282 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
283 Builder(const std::string &manifest_json);
284
286
287 /// @brief Set the no embed flag.
289
290 /// @brief Set the remote URL.
291 /// @param remote_url The remote URL to set.
292 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
293 void set_remote_url(const string &remote_url);
294
295 /// @brief Set the base path for loading resources from files.
296 /// Loads from memory if this is not set.
297 /// @param base_path The base path to set.
298 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
299 /// @deprecated This method is planned to be deprecated in a future release.
300 /// Usage should be limited and temporary. Use `add_resource` instead.
301 void set_base_path(const string &base_path);
302
303 /// @brief Add a resource to the builder.
304 /// @param uri The uri of the resource.
305 /// @param source The input stream to read the resource from.
306 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
307 void add_resource(const string &uri, istream &source);
308
309 /// @brief Add a resource to the builder.
310 /// @param uri The uri of the resource.
311 /// @param source_path The path to the resource file.
312 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
313 void add_resource(const string &uri, const std::filesystem::path &source_path);
314
315 /// @brief Add an ingredient to the builder.
316 /// @param ingredient_json Any fields of the ingredient you want to define.
317 /// @param format The format of the ingredient file.
318 /// @param source The input stream to read the ingredient from.
319 /// @throws C2pa::C2paException for errors encountered by the C2pa library.
320 void add_ingredient(const string &ingredient_json, const string &format, istream &source);
321
322 /// @brief Add an ingredient to the builder.
323 /// @param ingredient_json Any fields of the ingredient you want to define.
324 /// @param source_path The path to the ingredient file.
325 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
326 void add_ingredient(const string &ingredient_json, const std::filesystem::path &source_path);
327
328 /// @brief Add an action to the manifest the Builder is constructing.
329 /// @param action_json JSON string containing the action data.
330 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
331 void add_action(const string &action_json);
332
333 /// @brief Sign an input stream and write the signed data to an output stream.
334 /// @param format The format of the output stream.
335 /// @param source The input stream to sign.
336 /// @param dest The output stream to write the signed data to.
337 /// @param signer
338 /// @return A vector containing the signed manifest bytes.
339 /// @throws C2pa::C2paException for errors encountered by the C2PA library
340 /// @deprecated Use `sign(const string&, istream&, iostream&, Signer&)`
341 std::vector<unsigned char> sign(const string &format, istream &source, ostream &dest, Signer &signer);
342
343 /// @brief Sign an input stream and write the signed data to an output stream.
344 /// @param format The format of the output stream.
345 /// @param source The input stream to sign.
346 /// @param dest The in/output stream to write the signed data to.
347 /// @param signer
348 /// @return A vector containing the signed manifest bytes.
349 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
350 std::vector<unsigned char> sign(const string &format, istream &source, iostream &dest, Signer &signer);
351
352 /// @brief Sign a file and write the signed data to an output file.
353 /// @param source_path The path to the file to sign.
354 /// @param dest_path The path to write the signed file to.
355 /// @param signer A signer object to use when signing.
356 /// @return A vector containing the signed manifest bytes.
357 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
358 std::vector<unsigned char> sign(const path &source_path, const path &dest_path, Signer &signer);
359
360 /// @brief Create a Builder from an archive.
361 /// @param archive The input stream to read the archive from.
362 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
363 static Builder from_archive(istream &archive);
364
365 /// @brief Create a Builder from an archive
366 /// @param archive_path the path to the archive file
367 /// @throws C2pa::C2paException for errors encountered by the C2PA library
368 static Builder from_archive(const std::filesystem::path &archive_path);
369
370 /// @brief Write the builder to an archive stream.
371 /// @param dest The output stream to write the archive to.
372 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
373 void to_archive(ostream &dest);
374
375 /// @brief Write the builder to an archive file.
376 /// @param dest_path The path to write the archive file to.
377 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
378 void to_archive(const path &dest_path);
379
380 /// @brief Create a hashed placeholder from the builder.
381 /// @param reserved_size The size required for a signature from the intended signer.
382 /// @param format The format of the mime type or extension of the asset.
383 /// @return A vector containing the hashed placeholder.
384 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
385 std::vector<unsigned char> data_hashed_placeholder(uintptr_t reserved_size, const string &format);
386
387 /// @brief Sign a Builder using the specified signer and data hash.
388 /// @param signer The signer to use for signing.
389 /// @param data_hash The data hash ranges to sign. This must contain hashes unless and asset is provided.
390 /// @param format The mime format for embedding into. Use "c2pa" for an unformatted result.
391 /// @param asset An optional asset to hash according to the data_hash information.
392 /// @return A vector containing the signed data.
393 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
394 std::vector<unsigned char> sign_data_hashed_embeddable(Signer &signer, const string &data_hash, const string &format, istream *asset = nullptr);
395
396 /// @brief convert an unformatted manifest data to an embeddable format.
397 /// @param format The format for embedding into.
398 /// @param data An unformatted manifest data block from sign_data_hashed_embeddable using "c2pa" format.
399 /// @return A formatted copy of the data.
400 static std::vector<unsigned char> format_embeddable(const string &format, std::vector<unsigned char> &data);
401
402 /// @brief Returns a vector of mime types that the SDK is able to sign.
403 static std::vector<std::string> supported_mime_types();
404
405 private:
406 // Private constructor for Builder from an archive (todo: find a better way to handle this)
407 explicit Builder(istream &archive);
408 };
409}
410
411// Restore warnings
412#ifdef __GNUC__
413#pragma GCC diagnostic pop
414#endif
415
416#ifdef _MSC_VER
417#pragma warning(pop)
418#endif
419
420#endif // C2PA_H
#define C2PA_CPP_API
Definition c2pa.hpp:46
std::filesystem::path path
Definition c2pa.hpp:43
Builder class for creating a manifest.
Definition c2pa.hpp:275
void add_ingredient(const string &ingredient_json, const string &format, istream &source)
Add an ingredient to the builder.
Builder(const std::string &manifest_json)
Create a Builder from a manifest JSON string.
void set_remote_url(const string &remote_url)
Set the remote URL.
void to_archive(ostream &dest)
Write the builder to an archive stream.
void add_resource(const string &uri, const std::filesystem::path &source_path)
Add a resource to the builder.
void to_archive(const path &dest_path)
Write the builder to an archive file.
void add_ingredient(const string &ingredient_json, const std::filesystem::path &source_path)
Add an ingredient to the builder.
std::vector< unsigned char > sign(const path &source_path, const path &dest_path, Signer &signer)
Sign a file and write the signed data to an output file.
void set_no_embed()
Set the no embed flag.
void add_action(const string &action_json)
Add an action to the manifest the Builder is constructing.
std::vector< unsigned char > sign(const string &format, istream &source, ostream &dest, Signer &signer)
Sign an input stream and write the signed data to an output stream.
static std::vector< unsigned char > format_embeddable(const string &format, std::vector< unsigned char > &data)
convert an unformatted manifest data to an embeddable format.
std::vector< unsigned char > sign_data_hashed_embeddable(Signer &signer, const string &data_hash, const string &format, istream *asset=nullptr)
Sign a Builder using the specified signer and data hash.
static Builder from_archive(const std::filesystem::path &archive_path)
Create a Builder from an archive.
std::vector< unsigned char > data_hashed_placeholder(uintptr_t reserved_size, const string &format)
Create a hashed placeholder from the builder.
void add_resource(const string &uri, istream &source)
Add a resource to the builder.
std::vector< unsigned char > sign(const string &format, istream &source, iostream &dest, Signer &signer)
Sign an input stream and write the signed data to an output stream.
static std::vector< std::string > supported_mime_types()
Returns a vector of mime types that the SDK is able to sign.
static Builder from_archive(istream &archive)
Create a Builder from an archive.
void set_base_path(const string &base_path)
Set the base path for loading resources from files. Loads from memory if this is not set.
Definition c2pa.hpp:57
virtual const char * what() const noexcept
C2paException(string what)
IOStream Class wrapper for C2paStream.
Definition c2pa.hpp:158
C2paStream * c_stream
Definition c2pa.hpp:160
CppIOStream(IOStream &iostream)
Definition c2pa.hpp:162
Istream Class wrapper for C2paStream.
Definition c2pa.hpp:108
CppIStream & operator=(const CppIStream &)=delete
CppIStream(CppIStream &&)=delete
CppIStream & operator=(CppIStream &&)=delete
C2paStream * c_stream
Definition c2pa.hpp:110
CppIStream(IStream &istream)
Definition c2pa.hpp:112
CppIStream(const CppIStream &)=delete
Ostream Class wrapper for C2paStream.
Definition c2pa.hpp:137
CppOStream(OStream &ostream)
Definition c2pa.hpp:141
C2paStream * c_stream
Definition c2pa.hpp:139
Reader class for reading a manifest.
Definition c2pa.hpp:178
int64_t get_resource(const string &uri, const std::filesystem::path &path)
Get a resource from the reader and write it to a file.
bool is_embedded() const
Returns if the reader was created from an embedded manifest.
Definition c2pa.hpp:199
Reader(const std::string &format, std::istream &stream)
Create a Reader from a stream.
std::optional< std::string > remote_url() const
Returns the remote url of the manifest if this Reader obtained the manifest remotely.
int64_t get_resource(const string &uri, std::ostream &stream)
Get a resource from the reader and write it to an output stream.
string json()
Get the manifest as a json string.
Reader(const std::filesystem::path &source_path)
Create a Reader from a file path.
C2paReader * get_api_internal_raw_reader() const
Get the raw C2paReader pointer.
Definition c2pa.hpp:230
static std::vector< std::string > supported_mime_types()
Returns a vector of mime types that the SDK is able to read manifests from.
Signer class for creating a signer.
Definition c2pa.hpp:246
Signer(const string &alg, const string &sign_cert, const string &private_key, const string &tsa_uri=NULL)
Signer(SignerFunc *callback, C2paSigningAlg alg, const string &sign_cert, const string &tsa_uri)
Create a Signer from a callback function, signing algorithm, certificate, and TSA URI.
uintptr_t reserve_size()
Get the size to reserve for a signature for this signer.
C2paSigner * c2pa_signer()
Get the C2paSigner.
Signer(C2paSigner *signer)
Definition c2pa.hpp:258
Definition c2pa.hpp:49
C2paSignerInfo SignerInfo
Definition c2pa.hpp:52
std::vector< unsigned char >(const std::vector< unsigned char > &) SignerFunc
Signer Callback function type.
Definition c2pa.hpp:241