diff --git a/CMakeLists.txt b/CMakeLists.txt index a8ddef38..002ad772 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ cmake_minimum_required(VERSION 3.27) project(c2pa-c VERSION 0.13.0) # Set the version of the c2pa_rs library used -set(C2PA_VERSION "0.75.19") +set(C2PA_VERSION "0.75.21") set(CMAKE_POLICY_DEFAULT_CMP0135 NEW) set(CMAKE_C_STANDARD 17) diff --git a/tests/embeddable.test.cpp b/tests/embeddable.test.cpp index ff875ed5..f2a60862 100644 --- a/tests/embeddable.test.cpp +++ b/tests/embeddable.test.cpp @@ -402,231 +402,6 @@ TEST_F(EmbeddableTest, ContextSettingsPropagation) { EXPECT_GT(manifest.size(), 0) << "Context propagated successfully through workflow"; } -// Using archives with embedding -TEST_F(EmbeddableTest, ArchiveRoundTripWithContextAJpg) { - auto manifest_json = c2pa_test::read_text_file(c2pa_test::get_fixture_path("training.json")); - auto signer = c2pa_test::create_test_signer(); - - // Create context with custom settings (thumbnails disabled) - auto context = c2pa::Context(R"({ - "builder": { - "thumbnail": { - "enabled": false - } - } - })"); - - // Create initial builder and get baseline placeholder size - auto builder1 = c2pa::Builder(context, manifest_json); - auto placeholder1 = builder1.data_hashed_placeholder(signer.reserve_size(), "image/jpeg"); - size_t original_size = placeholder1.size(); - - // Save to archive - auto archive_path = get_temp_path("archive_a.c2pa"); - std::ofstream archive_stream(archive_path, std::ios::binary); - builder1.to_archive(archive_stream); - archive_stream.close(); - - // Load from archive using same context - auto builder2 = c2pa::Builder(context); - std::ifstream load_stream(archive_path, std::ios::binary); - builder2.with_archive(load_stream); - load_stream.close(); - - // Get placeholder from restored builder - auto placeholder2 = builder2.data_hashed_placeholder(signer.reserve_size(), "image/jpeg"); - - // Verify settings preserved by checking placeholder size matches - EXPECT_EQ(placeholder2.size(), original_size) - << "Settings should be preserved through archive round-trip"; -} - -// Using archives with embedding with asset having content credentials -TEST_F(EmbeddableTest, ArchiveRoundTripWithContextCJpg) { - auto manifest_json = c2pa_test::read_text_file(c2pa_test::get_fixture_path("training.json")); - auto signer = c2pa_test::create_test_signer(); - auto source_asset = c2pa_test::get_fixture_path("C.jpg"); - - auto context = c2pa::Context(R"({ - "builder": { - "thumbnail": { - "enabled": false - } - } - })"); - - auto builder1 = c2pa::Builder(context, manifest_json); - - auto archive_path = get_temp_path("archive_c.c2pa"); - std::ofstream archive_stream(archive_path, std::ios::binary); - builder1.to_archive(archive_stream); - archive_stream.close(); - - auto builder2 = c2pa::Builder(context); - std::ifstream load_stream(archive_path, std::ios::binary); - builder2.with_archive(load_stream); - load_stream.close(); - - auto placeholder = builder2.data_hashed_placeholder(signer.reserve_size(), "image/jpeg"); - - size_t embed_offset = 20; - std::string data_hash = R"({ - "exclusions": [{ - "start": )" + std::to_string(embed_offset) + R"(, - "length": )" + std::to_string(placeholder.size()) + R"( - }], - "name": "jumbf manifest", - "alg": "sha256", - "hash": "", - "pad": " " - })"; - - std::ifstream asset_stream(source_asset, std::ios::binary); - auto signed_manifest = builder2.sign_data_hashed_embeddable( - signer, data_hash, "image/jpeg", &asset_stream); - asset_stream.close(); - - // Verify the signed manifest has the expected size - EXPECT_EQ(signed_manifest.size(), placeholder.size()) - << "Settings preserved through archive round-trip"; -} - -// Using with ingredients -TEST_F(EmbeddableTest, ArchiveWithIngredientAJpg) { - auto signer = c2pa_test::create_test_signer(); - auto ingredient_path = c2pa_test::get_fixture_path("A.jpg"); - - // Create manifest with ingredient - std::string manifest_with_ingredient = R"({ - "claim_generator": "test_app/1.0", - "assertions": [ - { - "label": "c2pa.actions", - "data": { - "actions": [ - { - "action": "c2pa.created" - } - ] - } - } - ], - "ingredients": [ - { - "title": "A.jpg", - "relationship": "parentOf" - } - ] - })"; - - auto context = c2pa::Context(R"({ - "builder": { - "thumbnail": { - "enabled": false - } - } - })"); - - auto builder1 = c2pa::Builder(context, manifest_with_ingredient); - - // Add ingredient using the proper API - std::string ingredient_json = R"({"title": "A.jpg"})"; - builder1.add_ingredient(ingredient_json, ingredient_path); - - // Get baseline placeholder size - auto placeholder1 = builder1.data_hashed_placeholder(signer.reserve_size(), "image/jpeg"); - size_t original_size = placeholder1.size(); - - // Archive and restore - auto archive_path = get_temp_path("archive_with_ingredient_a.c2pa"); - std::ofstream archive_stream(archive_path, std::ios::binary); - builder1.to_archive(archive_stream); - archive_stream.close(); - - auto builder2 = c2pa::Builder(context); - std::ifstream load_stream(archive_path, std::ios::binary); - builder2.with_archive(load_stream); - load_stream.close(); - - // Get placeholder from restored builder - auto placeholder2 = builder2.data_hashed_placeholder(signer.reserve_size(), "image/jpeg"); - - // Verify the ingredient survived the round-trip (size should match since ingredients are included) - EXPECT_EQ(placeholder2.size(), original_size) - << "Ingredient should be preserved through archive round-trip"; -} - -// Using with ingredients with asset having content credentials -TEST_F(EmbeddableTest, ArchiveWithIngredientCJpg) { - auto signer = c2pa_test::create_test_signer(); - auto ingredient_path = c2pa_test::get_fixture_path("C.jpg"); - - std::string manifest_with_ingredient = R"({ - "claim_generator": "test_app/1.0", - "assertions": [ - { - "label": "c2pa.actions", - "data": { - "actions": [ - { - "action": "c2pa.created" - } - ] - } - } - ], - "ingredients": [ - { - "title": "C.jpg", - "relationship": "parentOf" - } - ] - })"; - - auto context = c2pa::Context(R"({ - "builder": { - "thumbnail": { - "enabled": false - } - } - })"); - - auto builder1 = c2pa::Builder(context, manifest_with_ingredient); - std::string ingredient_json = R"({"title": "C.jpg"})"; - builder1.add_ingredient(ingredient_json, ingredient_path); - - // Archive round-trip - auto archive_path = get_temp_path("archive_with_ingredient_c.c2pa"); - std::ofstream archive_stream(archive_path, std::ios::binary); - builder1.to_archive(archive_stream); - archive_stream.close(); - - auto builder2 = c2pa::Builder(context); - std::ifstream load_stream(archive_path, std::ios::binary); - builder2.with_archive(load_stream); - load_stream.close(); - - // Verify we can create placeholders and sign after round-trip - auto placeholder2 = builder2.data_hashed_placeholder(signer.reserve_size(), "image/jpeg"); - EXPECT_GT(placeholder2.size(), 0) << "Should be able to create placeholder after archive round-trip"; - - // Verify we can sign - std::string data_hash = R"({ - "exclusions": [{ - "start": 20, - "length": )" + std::to_string(placeholder2.size()) + R"( - }], - "name": "jumbf manifest", - "alg": "sha256", - "hash": "gWZNEOMHQNiULfA/tO5HD2awOwYMA3tnfUPApIr9csk=", - "pad": " " - })"; - - auto manifest = builder2.sign_data_hashed_embeddable( - signer, data_hash, "image/jpeg", nullptr); - EXPECT_GT(manifest.size(), 0) << "Should be able to sign after archive round-trip"; -} - // Verify different formats TEST_F(EmbeddableTest, MultipleFormats) { auto manifest_json = c2pa_test::read_text_file(c2pa_test::get_fixture_path("training.json"));